问题
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
回答1:
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 */ };
回答2:
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...]
回答3:
You could create public events in your custom control, something like NextButtonClicked and PreviousButtonClicked.
回答4:
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