WPF如何将事件传递给兄弟元素

发布于 2024-09-06 12:50:27 字数 2252 浏览 8 评论 0原文

我已阅读帖子 Button.MouseDown 接下来我想再问 1 个问题。 我的XAML如下:

    <Window.Resources>
    <Style TargetType="{x:Type ContentControl}">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Padding" Value="10" />
        <Setter Property="Background" Value="PaleGreen" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ContentControl}">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                        <ContentPresenter/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<StackPanel Tag="Panel" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
    <ContentControl BorderBrush="Red" Tag="C1" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
        <ContentControl BorderBrush="Green" Tag="C2" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
            <StackPanel Tag="Panel2" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
                <ContentControl Content="Click Me" BorderBrush="Blue" Tag="C3" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown"/>
                <ContentControl Content="Click Me2" BorderBrush="Blue" Tag="C33" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown"/>
            </StackPanel>
        </ContentControl>
    </ContentControl>
</StackPanel>

我的cs如下:

        private void PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        Debug.WriteLine(((FrameworkElement) sender).Tag + " Preview");
    }

    private void MouseDown(object sender, MouseButtonEventArgs e)
    {
        Debug.WriteLine(((FrameworkElement) sender).Tag + " Bubble");
    }

如何将鼠标向上/向下事件从C3传输到C33?基本上我希望来自一个兄弟姐妹的所有事件也能到达其他兄弟姐妹。

I have read the post Button.MouseDown
In continuation to that I want to ask 1 more question.
My XAML is as follows :

    <Window.Resources>
    <Style TargetType="{x:Type ContentControl}">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Padding" Value="10" />
        <Setter Property="Background" Value="PaleGreen" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ContentControl}">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                        <ContentPresenter/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<StackPanel Tag="Panel" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
    <ContentControl BorderBrush="Red" Tag="C1" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
        <ContentControl BorderBrush="Green" Tag="C2" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
            <StackPanel Tag="Panel2" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown">
                <ContentControl Content="Click Me" BorderBrush="Blue" Tag="C3" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown"/>
                <ContentControl Content="Click Me2" BorderBrush="Blue" Tag="C33" PreviewMouseDown="PreviewMouseDown" MouseDown="MouseDown"/>
            </StackPanel>
        </ContentControl>
    </ContentControl>
</StackPanel>

My cs is as follows :

        private void PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        Debug.WriteLine(((FrameworkElement) sender).Tag + " Preview");
    }

    private void MouseDown(object sender, MouseButtonEventArgs e)
    {
        Debug.WriteLine(((FrameworkElement) sender).Tag + " Bubble");
    }

How can I transfer mouse up/down events from C3 to C33? Basically I want all events from 1 sibling to reach other too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

娇女薄笑 2024-09-13 12:50:27

从 C3 的 EventHandler 中,您可以调用 C33 的 RaiseEvent 方法:

private void C3_MouseDown(object sender, MouseButtonEventArgs e)
{
  C33.RaiseEvent(e);
}

顺便说一句,我注意到您正在使用 Tag 来命名元素。更合适的属性是 Name 属性。一般规则是,Tag 属性的使用仅适用于大约 0.001% 的 WPF 程序(十万分之一)。在所有常用的情况下,都有更好的方法来做同样的事情。

From C3's EventHandler you can call C33's RaiseEvent method:

private void C3_MouseDown(object sender, MouseButtonEventArgs e)
{
  C33.RaiseEvent(e);
}

As an aside, I notice that you are using Tag to name your elements. A much more appropriate property to use for this would be the Name property. A general rule is that the use of the Tag property is only appropriate in roughtly 0.001% of WPF programs (1 in 100,000). In all cases where it is commonly used there is a much better way to do the same thing.

深海蓝天 2024-09-13 12:50:27

我为这种情况编写了一个行为:

using System.Reflection;
using System.Windows;
using System.Windows.Interactivity;

namespace Behaviors
{
    public class RedirectRoutedEventBehavior : Behavior<UIElement>
    {
        public static readonly DependencyProperty RedirectTargetProperty =
            DependencyProperty.Register("RedirectTarget", typeof(UIElement),
                typeof(RedirectRoutedEventBehavior),
                new PropertyMetadata(null));

        public static readonly DependencyProperty RoutedEventProperty =
            DependencyProperty.Register("RoutedEvent", typeof(RoutedEvent), typeof(RedirectRoutedEventBehavior),
                new PropertyMetadata(null, OnRoutedEventChanged));

        public UIElement RedirectTarget
        {
            get => (UIElement) this.GetValue(RedirectTargetProperty);
            set => this.SetValue(RedirectTargetProperty, value);
        }

        public RoutedEvent RoutedEvent
        {
            get => (RoutedEvent) this.GetValue(RoutedEventProperty);
            set => this.SetValue(RoutedEventProperty, value);
        }

        private static MethodInfo MemberwiseCloneMethod { get; }
            = typeof(object)
                .GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);

        private static void OnRoutedEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((RedirectRoutedEventBehavior) d).OnRoutedEventChanged((RoutedEvent) e.OldValue, (RoutedEvent) e.NewValue);
        }

        private void OnRoutedEventChanged(RoutedEvent oldValue, RoutedEvent newValue)
        {
            if (this.AssociatedObject == null)
            {
                return;
            }

            if (oldValue != null)
            {
                this.AssociatedObject.RemoveHandler(oldValue, new RoutedEventHandler(this.EventHandler));
            }

            if (newValue != null)
            {
                this.AssociatedObject.AddHandler(newValue, new RoutedEventHandler(this.EventHandler));
            }
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            if (this.RoutedEvent != null)
            {
                this.AssociatedObject.AddHandler(this.RoutedEvent, new RoutedEventHandler(this.EventHandler));
            }
        }

        protected override void OnDetaching()
        {
            if (this.RoutedEvent != null)
            {
                this.AssociatedObject.RemoveHandler(this.RoutedEvent, new RoutedEventHandler(this.EventHandler));
            }

            base.OnDetaching();
        }

        private static RoutedEventArgs CloneEvent(RoutedEventArgs e)
        {
            return (RoutedEventArgs) MemberwiseCloneMethod.Invoke(e, null);
        }

        private void EventHandler(object sender, RoutedEventArgs e)
        {
            var newEvent = CloneEvent(e);
            e.Handled = true;

            if (this.RedirectTarget != null)
            {
                newEvent.Source = this.RedirectTarget;
                this.RedirectTarget.RaiseEvent(newEvent);
            }
        }
    }
}

用法:

<ContentControl x:Name="A" Content="Click Me" BorderBrush="Blue">
    <i:Interaction.Behaviors>
        <behaviors:RedirectRoutedEventBehavior RoutedEvent="UIElement.MouseDown" 
                                           RedirectTarget="{Binding ElementName=B}" />
        <behaviors:RedirectRoutedEventBehavior RoutedEvent="UIElement.PreviewMouseDown" 
                                           RedirectTarget="{Binding ElementName=B}" />
    </i:Interaction.Behaviors>
</ContentControl>
<ContentControl x:Name="B" Content="Click Me2" BorderBrush="Blue" />

这将 MouseDownPreviewMouseDown 事件从 A 重定向到 B

您需要 Install-Package System.Windows.Interactivity.WPF 到您的项目中,并需要 xmlns 声明:

xmlns:behaviors="clr-namespace:Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

I wrote a behavior for this kind of scenario:

using System.Reflection;
using System.Windows;
using System.Windows.Interactivity;

namespace Behaviors
{
    public class RedirectRoutedEventBehavior : Behavior<UIElement>
    {
        public static readonly DependencyProperty RedirectTargetProperty =
            DependencyProperty.Register("RedirectTarget", typeof(UIElement),
                typeof(RedirectRoutedEventBehavior),
                new PropertyMetadata(null));

        public static readonly DependencyProperty RoutedEventProperty =
            DependencyProperty.Register("RoutedEvent", typeof(RoutedEvent), typeof(RedirectRoutedEventBehavior),
                new PropertyMetadata(null, OnRoutedEventChanged));

        public UIElement RedirectTarget
        {
            get => (UIElement) this.GetValue(RedirectTargetProperty);
            set => this.SetValue(RedirectTargetProperty, value);
        }

        public RoutedEvent RoutedEvent
        {
            get => (RoutedEvent) this.GetValue(RoutedEventProperty);
            set => this.SetValue(RoutedEventProperty, value);
        }

        private static MethodInfo MemberwiseCloneMethod { get; }
            = typeof(object)
                .GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);

        private static void OnRoutedEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((RedirectRoutedEventBehavior) d).OnRoutedEventChanged((RoutedEvent) e.OldValue, (RoutedEvent) e.NewValue);
        }

        private void OnRoutedEventChanged(RoutedEvent oldValue, RoutedEvent newValue)
        {
            if (this.AssociatedObject == null)
            {
                return;
            }

            if (oldValue != null)
            {
                this.AssociatedObject.RemoveHandler(oldValue, new RoutedEventHandler(this.EventHandler));
            }

            if (newValue != null)
            {
                this.AssociatedObject.AddHandler(newValue, new RoutedEventHandler(this.EventHandler));
            }
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            if (this.RoutedEvent != null)
            {
                this.AssociatedObject.AddHandler(this.RoutedEvent, new RoutedEventHandler(this.EventHandler));
            }
        }

        protected override void OnDetaching()
        {
            if (this.RoutedEvent != null)
            {
                this.AssociatedObject.RemoveHandler(this.RoutedEvent, new RoutedEventHandler(this.EventHandler));
            }

            base.OnDetaching();
        }

        private static RoutedEventArgs CloneEvent(RoutedEventArgs e)
        {
            return (RoutedEventArgs) MemberwiseCloneMethod.Invoke(e, null);
        }

        private void EventHandler(object sender, RoutedEventArgs e)
        {
            var newEvent = CloneEvent(e);
            e.Handled = true;

            if (this.RedirectTarget != null)
            {
                newEvent.Source = this.RedirectTarget;
                this.RedirectTarget.RaiseEvent(newEvent);
            }
        }
    }
}

Usage:

<ContentControl x:Name="A" Content="Click Me" BorderBrush="Blue">
    <i:Interaction.Behaviors>
        <behaviors:RedirectRoutedEventBehavior RoutedEvent="UIElement.MouseDown" 
                                           RedirectTarget="{Binding ElementName=B}" />
        <behaviors:RedirectRoutedEventBehavior RoutedEvent="UIElement.PreviewMouseDown" 
                                           RedirectTarget="{Binding ElementName=B}" />
    </i:Interaction.Behaviors>
</ContentControl>
<ContentControl x:Name="B" Content="Click Me2" BorderBrush="Blue" />

This redirects MouseDown and PreviewMouseDown events from A to B.

You need Install-Package System.Windows.Interactivity.WPF to your project, and xmlns declarations:

xmlns:behaviors="clr-namespace:Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文