WPF - 在自定义控件上处理自定义附加事件

7 c# wpf user-controls attached-properties

我有一个声明的路由事件(名称已被更改以保护无辜者):

public class DragHelper : DependencyObject {
    public static readonly RoutedEvent DragCompleteEvent = EventManager.RegisterRoutedEvent(
        "DragComplete",
        RoutingStrategy.Bubble,
        typeof(DragRoutedEventHandler),
        typeof(DragHelper)
    );

    public static void AddDragCompleteHandler( DependencyObject dependencyObject, DragRoutedEventHandler handler ) {
        UIElement element = dependencyObject as UIElement;
        if (element != null) {
            element.AddHandler(DragCompleteEvent, handler);
        }
    }

    public static void RemoveDragCompleteHandler( DependencyObject dependencyObject, DragRoutedEventHandler handler ) {
        UIElement element = dependencyObject as UIElement;
        if (element != null) {
            element.RemoveHandler(DragCompleteEvent, handler);
        }
    }
Run Code Online (Sandbox Code Playgroud)

很标准的东西.在XAML中,我有一个包含单个自定义控件的DataTemplate.我试图将此事件(以及一些其他附加属性)附加到控件:

<DataTemplate ...>
    <My:CustomControl
        My:DragHelper.IsDragSource="True"
        My:DragHelper.DragComplete="DragCompleteHandler" />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

这无法产生预期的结果.具体来说,虽然调用了为DragComplete事件调用RaiseEvent()的代码,但从不调用该处理程序.事实上,它也不是连接到此XAML文件中其他位置的任何其他自定义路由事件的处理程序.

我尝试更改路由事件的名称,并尝试将数据模板从具有DataType的模板转换为具有x:Key的模板.这没有产生明显的行为变化.

但是,如果我将My:CustomControl更改为任何内置的WPF控件(例如TextBlock),则事件将完全按照我要求的方式触发.类似地,如果我将自定义控件替换为我的项目中的任何其他自定义UserControl子类,则行为将恢复为已损坏的无事件似乎处于获取状态.

这对我来说并不是很有意义.为了让这个场景有效,我需要做些什么吗?看起来应该没关系.我想有可能在我的所有自定义控件中都有一个特定的事情会导致事件处理中断,但我在目前为止尝试的三个或四个自定义控件中没有看到任何常见的东西.

Ken*_*art 1

您还没有发布所有代码,因此我必须推断并组合我自己的版本。对我来说效果很好。也许与您的代码进行比较和对比:

Window1.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void DragCompleteHandler(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("YEP");
        }
    }

    public class CustomControl : TextBox
    {
    }

    public class DragHelper : DependencyObject
    {
        public static readonly DependencyProperty IsDragSourceProperty = DependencyProperty.RegisterAttached("IsDragSource",
            typeof(bool),
            typeof(DragHelper),
            new FrameworkPropertyMetadata(OnIsDragSourceChanged));

        public static bool GetIsDragSource(DependencyObject depO)
        {
            return (bool)depO.GetValue(IsDragSourceProperty);
        }

        public static void SetIsDragSource(DependencyObject depO, bool ids)
        {
            depO.SetValue(IsDragSourceProperty, ids);
        }

        public static readonly RoutedEvent DragCompleteEvent = EventManager.RegisterRoutedEvent(
            "DragComplete",
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(DragHelper)
        );

        public static void AddDragCompleteHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            UIElement element = dependencyObject as UIElement;
            if (element != null)
            {
                element.AddHandler(DragCompleteEvent, handler);
            }
        }

        public static void RemoveDragCompleteHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
        {
            UIElement element = dependencyObject as UIElement;
            if (element != null)
            {
                element.RemoveHandler(DragCompleteEvent, handler);
            }
        }

        private static void OnIsDragSourceChanged(DependencyObject depO, DependencyPropertyChangedEventArgs e)
        {
            (depO as TextBox).TextChanged += delegate
            {
                (depO as TextBox).RaiseEvent(new RoutedEventArgs(DragCompleteEvent, null));
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

窗口1.xaml

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <DataTemplate x:Key="Test">
            <local:CustomControl
                local:DragHelper.IsDragSource="True"
                local:DragHelper.DragComplete="DragCompleteHandler" />
        </DataTemplate>
    </Window.Resources>

    <ContentControl ContentTemplate="{StaticResource Test}"/>
</Window>
Run Code Online (Sandbox Code Playgroud)