在WPF中将事件从样式传播到MainWindow

本文关键字:样式 传播 MainWindow 事件 WPF | 更新日期: 2023-09-27 18:30:00

我在一个单独的XAML CustomTabItem.xaml中有一个自定义样式,它引发一个事件,如:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                x:Class="myProject.CustomTabItem">
    ...
    ...
    <MenuItem Header="One">
        <MenuItem.Style>
            <Style TargetType="{x:Type MenuItem}">
                <EventSetter Event="Click" Handler="ClickNewSpaceOne"/>
            </Style>
        </MenuItem.Style>
    </MenuItem>
    ...
    ...
</ResourceDictionary>

这很容易在我创建的名为CustomTabItem.xaml.cs:的文件中引发一个事件

namespace myProject
{
    partial class CustomTabItem
    {
        private void ClickNewSpaceOne(object sender, RoutedEventArgs e)
        {
            //do stuff here
        }
    }
}

这一切都很好,但我现在需要在MainWindow中引发一个事件(当然是在事件处理程序ClickNewSpaceOne中),但我不知道如何将此事件传播到MainWindow

我找到了这篇文章,但它看起来并不是完全一样的情况,所以我没有找到任何不同的文章或任何答案,我都会非常感激。

在WPF中将事件从样式传播到MainWindow

在这种情况下使用EventSetter的做法不是最好的。原因如下:

  • 他被绑定到BAML文件,该文件应该是事件处理程序

因为它仅限于事件的全局函数,所以他只是在xaml.cs文件中查找事件处理程序。也正因为如此,从MSDN:

不能在主题资源字典中包含的样式中使用事件设置器。

  • 不能在触发器中设置EventSetter

引用自link:

由于使用EventSetter连接事件处理程序是通过IStyleConnector接口引导的编译时功能,因此XAML编译器使用另一个名为IComponentConnector的接口来连接独立XAML元素的事件处理程序。

What alternatives?

1 - Attached dependency property

使用附加的依赖项属性及其UIPropertyMetadata,可以实现必要的逻辑。例如:

// GetValue
// SetValue
public static readonly DependencyProperty SampleProperty =
                                      DependencyProperty.RegisterAttached("Sample",
                                      typeof(bool),
                                      typeof(SampleClass),
                                      new UIPropertyMetadata(false, OnSample));
private static void OnSample(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue is bool && ((bool)e.NewValue) == true)
    {
        // do something...
    }
}

更多信息可以在这里找到:

如何继承WPF风格中的按钮行为?

从用户退出应用程序控制

在没有数据绑定的情况下登录失败时,如何清除PasswordBox的内容?

2 - Commands

WPF中的命令是非常强大的。引用自MSDN:

第一个目的是将语义和调用命令的对象与执行命令的逻辑分离。这允许多个不同的源调用相同的命令逻辑,并允许为不同的目标定制命令逻辑。

在这种情况下,它们可以并且应该在StylesTemplatesDataTemplates中使用。在样式中,您可以设置这样的命令:

<Setter Property="Command" 
        Value="{Binding DataContext.YourCommand,
                RelativeSource={Relative Source AncestorType={x:Type Control}}}">

此外,如果您想引用该命令,可以将该命令声明为静态属性,然后可以使用Static扩展名来引用它。

3 - Using EventTrigger with Interactivity

在这种情况下,命令由EventTrigger调用。例如:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseEnter" >
        <i:InvokeCommandAction Command="{Binding MyCommand}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

更多信息,可以在这里找到:

在MVVM 的XAML中使用EventTrigger

将WPF事件绑定到MVVM Viewmodel命令