从xaml中的父类附加事件处理程序

本文关键字:事件处理 程序 父类 xaml | 更新日期: 2023-09-27 18:29:18

我有一个窗口的基类,它包含许多此类窗口通用的事件处理程序(它们激发通用的验证方法)。

下面是一个示例事件处理程序:

protected virtual void ValidateTextBoxTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
    ValidateProperty((FrameworkElement)sender, TextBox.TextProperty);
}

其中大约有20种,涵盖了常见的控件。

每个窗口实例都是从基的一个子类构建的。在子类的.xaml中,我做:

<TextBox 
    TextChanged="ValidateTextBoxTextChanged"/>

但是当我导航到这个窗口时,我会得到以下错误:

未能分配给属性"System.Windows.Controls.TextBox.TextChanged".

所以它没有找到事件处理程序。有没有一种优雅的方法可以在不在每个子类中复制事件处理程序的情况下分配事件处理程序(大约30个子类,并且还在计数)?

从xaml中的父类附加事件处理程序

这很有趣——事件机制的一个限制似乎是只检查类后面的部分代码,而不检查它的基类。(这个问题也在这里和这里提出。)我也想不出一个理想的解决方案。

当然,您可以通过在每个子类中放置一个伪覆盖来修复错误:

protected override void ValidateTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
    base.ValidateTextBoxTextChanged(sender, e);
}

当然,这似乎很麻烦。另一种选择是使用触发器/操作组合来调用基类方法:

<TextBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="TextChanged">
            <ei:CallMethodAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType=local:BaseWindow}}"  MethodName="ValidateTextBoxTextChanged" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

为此,您需要公开该方法。您可以使用上面的变体来简化语法并减少绑定的数量:使用附加的属性来应用触发器,将验证方法放在具有可选重写的静态资源中。


另一种可能的方法是对TextBox本身进行子类化,并将验证逻辑放在那里。您可以公开一个依赖属性,以允许扩展TextBox的实例覆盖默认验证逻辑。

我在代码中完成了这项工作。我有一个基本的xaml页面,有几个下降

<Page x:Class="mycls"><Button x:Name="mybrn"/></Page>

以及一些继承它的观点:

<local:mycls x:Class="mychild"></local:mycls>

如果我在xaml中分配监听器,它在子视图中不起作用。但它背后的代码是有效的:

public mycls()
{
    InitializeComponent()
    (this.FindName("mybtn") as Button).Click += mybtn_click;
}

在这个子视图之后,"inherit"也是一个处理程序。