如何将EventSetter.Handler特定于其他类的方法

时间:2013-11-26 11:55:05

标签: c# wpf xaml

我有这段代码

<EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="TextBox_PreviewMouseLeftButtonDown"/>

我在Handler中编写的方法必须是Window xaml类的方法 如何具体到其他类方法?

2 个答案:

答案 0 :(得分:3)

要实现您正在尝试的内容,您可以创建一个公共基类,并在该类中定义事件处理程序。

我的样本中的基类:

public class MyWindowBase : Window
{
    protected void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        // Your handling code goes here.. 
    }
}

然后,让所有你的Window派生自这个新的基类:

来自我的示例的MainWindow.xaml:

<wpfApplication5:MyWindowBase x:Class="WpfApplication5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:wpfApplication5="clr-namespace:WpfApplication5"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="{x:Type TextBox}">
            <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox Name="TextBox1" />
    </Grid>
</wpfApplication5:MyWindowBase>

您还必须在代码隐藏中更新基类:

public partial class MainWindow : MyWindowBase
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

这样,所有窗口都可以使用基类中定义的单个处理程序。唯一的缺点是你必须在所有XAML文件中重复EventSetter代码(当然,无论你想使用那个单一的处理程序)。

选项2

另一个选项是将EventSetter XAML移动到ResourceDictionary,并为ResourceDictionary提供代码隐藏,并在那里安装EventHandler。

ResourceDictionary XAML

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="WpfApplication5.Dictionary1">
    <Style TargetType="{x:Type TextBox}">
        <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"/>
    </Style>
</ResourceDictionary>

和Codebehind:

public partial class Dictionary1 : ResourceDictionary
{
    public Dictionary1()
    {
        InitializeComponent();
    }

    void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(sender.ToString());
    }
}

然后你的窗口XAML会变成这样:

<Window x:Class="WpfApplication5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox Name="TextBox1" />
    </Grid>
</Window>

希望这会有所帮助,或者就如何解决问题提供一些想法。

答案 1 :(得分:0)

使用EventSetter,您只能在声明它的XAML文件后面的代码中使用处理程序。如果您尝试使用XML名称空间前缀从另一个类引用方法,那么您将从编译器中收到错误:

  

只有生成的或代码隐藏类的实例方法才有效。

我能想到这样做的唯一方法是,如果你的代码背后有一个带有所需处理程序的类的引用。在这种情况下,您可以这样做:

在处理类中:

public void HandleMouseButtonEvent(object sender, MouseButtonEventArgs e)
{
    // handle event here
}

在背后的代码中:

public void MouseButtonEventHandler(object sender, MouseButtonEventArgs e)
{
    handlingClass.HandleMouseButtonEvent(sender, e);
}