在WPF中,如何为Template中设计的FrameworkElement添加EventHandler? [英] In WPF, how to add an EventHandler for a FrameworkElement designed in Template?

查看:228
本文介绍了在WPF中,如何为Template中设计的FrameworkElement添加EventHandler?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在外部资源字典中为 ListBox 项定义了以下 DataTemplate

I have defined the following DataTemplate for ListBox items in an external resource dictionary:

<DataTemplate x:Key="MyListBoxItemTemplate" DataType="{x:Type entities:Track}">
    <StackPanel>       
        <TextBlock Text="Here's the slider:" />
        <Slider Name="MySlider" Height="23" Minimum="0" />
    </StackPanel>
</DataTemplate>

我需要为Slider的 ValueChanged 事件。我不知道我应该在哪里编写代码,因为在模板中为控件指定事件处理程序是不切实际的。

I need to provide an event handler method for Slider's ValueChanged event. I don't know where am I supposed to write that code as it is impractical to specify event handler for a control within a template.

我一直在搜索解决方案,发现我应该在 OnApplyTemplate()方法。我的猜测是它应该是这样或类似的:

I've been googling for the solution and found that I should add the event handler in the override of the OnApplyTemplate() method. My guess is that it should look something like this or similar:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    // Is the following initialization even going to work!?!?
    Slider MySlider = this.FindName("MySlider") as Slider;
    SeekSlider.ValueChanged += 
        new RoutedPropertyChangedEventHandler<double>(SeekSlider_ValueChanged);
}

但是我应该在哪里写这个方法? OnApplyTemplate覆盖仅适用于ControlTemplates或是否包括我的场景?应该提供ControlTemplate而不是DataTemplate吗?我提供的方法的身体是否正确?

But where should I write this method? Does OnApplyTemplate overriding only applies to ControlTemplates or is my scenario included as well? Should I provide ControlTemplate instead of DataTemplate? Is the body of the method I have provided correct?

请帮忙。谢谢。

推荐答案

使用 OnApplyTemplate ControlTemplate 。例如,如果您已经将 TextBox 子类化,则可以像

Using the OnApplyTemplate approach will work if you if you're working with the ControlTemplate for a Control. For example, if you've subclassed TextBox you could do this like

public class MyTextBox : TextBox
{
    public override void OnApplyTemplate()
    {
        MySlider MySlider = GetTemplateChild("MySlider") as MySlider;
        if (MySlider != null)
        {
            MySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(MySlider_ValueChanged);
        }
        base.OnApplyTemplate();
    }
    void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        //...
    }
}

我不认为这种方法会在你的情况下奏效。您可以使用Loaded事件 ListBoxItem ,并在事件处理程序

I don't think this approach will work in your situation however. You could use the Loaded event for ListBoxItem and find the Slider in the visual tree in the event handler

<ListBox ...>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <EventSetter Event="Loaded" Handler="ListBoxItem_Loaded"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <!--...-->
</ListBox>

后面的代码

private void ListBoxItem_Loaded(object sender, RoutedEventArgs e)
{
    ListBoxItem listBoxItem = sender as ListBoxItem;
    Slider MySlider = GetVisualChild<Slider>(listBoxItem);
    MySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(MySlider_ValueChanged);
}
void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{

}

GetVisualChild

private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
    T child = default(T);

    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

这篇关于在WPF中,如何为Template中设计的FrameworkElement添加EventHandler?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆