I have my generic.xaml containing the following code:
<ControlTemplate TargetType="local:customVideoControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="600"/>
<RowDefinition Height="200"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<MediaElement x:Name="customMediaPlayer" Source="{TemplateBinding CustomMediaSource}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}"
Grid.Row="0" Grid.ColumnSpan="3"
/>
<ToggleButton x:Name="playPauseBtn" Height="50" Width="50" Content="Pause" Grid.Row="1" Grid.Column="0"/>
<Button x:Name="prevBtn" Height="50" Width="50" Content="Prev" Grid.Row="1" Grid.Column="1"/>
<Button x:Name="nextBtn" Height="50" Width="50" Content="Next" Grid.Row="1" Grid.Column="2"/>
</Grid>
</ControlTemplate>
Now on applyTemplate , I am accessing the controls like below:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
ToggleButton playPauseBtn = GetTemplateChild("playPauseBtn") as ToggleButton;
Button prevBtn= GetTemplateChild("prevBtn") as Button;
Button nextBtn = GetTemplateChild("nextBtn") as Button;
MediaElement customMediaPlayer = GetTemplateChild("customMediaPlayer") as MediaElement;
playPauseBtn.Checked += (obj, Args) =>
{
customMediaPlayer.Pause();
playPauseBtn.Content = "Play";
};
playPauseBtn.Unchecked += (obj, Args) =>
{
customMediaPlayer.Play();
playPauseBtn.Content = "Pause";
};
nextBtn.Click += (obj, Args) =>
{
customMediaPlayer.Source=new Uri(CustomMediaSource.ToString(),UriKind.RelativeOrAbsolute);
};
prevBtn.Click += (obj, Args) =>
{
customMediaPlayer.Source = new Uri(CustomMediaSource.ToString(), UriKind.RelativeOrAbsolute);
};
}
Now I want acccess the nextBtn, in the page where I am implementing like
CustomVideoControl myVControl=new CustomVideoControl();
This will create the instance of the control, but I want to do something on the click of next and previous button, thta is present inside the CustomVideoControl in generic.xaml. Any help will be greatly appreciated.
Thanks, Subhen
You just need to add a couple of events to your Control.
public event EventHandler MovedPrevious
public event EventHandler MovedNext
Now this are typically implemented like this:-
protected virtual void OnMovedPrevious(EventArgs e)
{
var handler = MovedPrevious;
if (handler != null)
handler(this, e);
}
protected virtual void OnMovedNext(EventArgs e)
{
var handler = MovedNext;
if (handler != null)
handler(this, e);
}
Now in your existing click events:-
nextBtn.Click += (obj, Args) =>
{
customMediaPlayer.Source=new Uri(CustomMediaSource.ToString(),UriKind.RelativeOrAbsolute); //No idea what this doing
OnMovedNext(EventArgs.Empty);
};
prevBtn.Click += (obj, Args) =>
{
customMediaPlayer.Source = new Uri(CustomMediaSource.ToString(), UriKind.RelativeOrAbsolute); //No idea what this is doing either
OnMovedPrevious(EventArgs.Empty);
};
Now in your consuming code you can do this sort of thing:-
CustomVideoControl myVControl=new CustomVideoControl();
myVControl.MovedNext += (s, args) => { /* deal with next */ };
myVControl.MovedPrevious += (s, args) => { /* deal with previous */ };
Sorry, but you're doing it wrong. There's no good reason why you should have a reference to elements inside a DataTemplate IMO. [...Read more at this forum post...]
You could create public events in your custom control, something like NextButtonClicked and PreviousButtonClicked.
I have a feeling, that you're trying to mimic EventSetter behaviour. If I'm right, please just take a look on this simple example:
<Style TargetType="{x:Type Button}" x:Key="SomeID">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
</Trigger>
</Style.Triggers>
<EventSetter Event="MouseUp" Handler="DoSomething_Click"></EventSetter>
</Style>
This code assigns your custom event to some text block's regular action directly from XAML (you don't have to pollute your code behind with accessing controls' properties).
I hope this is helpful, but if not, please give me a shout.
Edit:
Sorry for not being perfectly clear (this was just a quickly pasted code snippet). Please have a look on a complete example:
Styles for your next/previous buttons:
<Style TargetType="{x:Type Button}" x:Key="PreviousButtonstyle">
<EventSetter Event="Click" Handler="OnMovedPrevious"></EventSetter>
</Style>
<Style TargetType="{x:Type Button}" x:Key="NextButtonstyle">
<EventSetter Event="Click" Handler="OnMovedNext"></EventSetter>
</Style>
Code behind:
public event EventHandler MovedPrevious;
public event EventHandler MovedNext;
protected void OnMovedPrevious(object sender, RoutedEventArgs e)
{
if (MovedPrevious != null)
{
MovedPrevious(this, e);
}
}
protected void OnMovedNext(object sender, RoutedEventArgs e)
{
if (MovedNext != null)
{
MovedNext(this, e);
}
}
Since now on you can access OnMovedNext and OnMovedPrevious directly from your control's handling conrol/whatever just as Anthony posted.
Sorry if my previous answer was confusing, but it supposed to be just an inspiration what to do :)
Edit:
I haven't noticed that this regards only Silverlight for which I apologize :) But, it works perfectly for WPF if you wish to try.
来源:https://stackoverflow.com/questions/2690177/how-to-access-a-button-present-inside-a-custom-control-from-the-implementing-pa