C# 重写元数据和默认样式之间的差异

C# 重写元数据和默认样式之间的差异,c#,wpf,C#,Wpf,在制作一个用作拖放目标的自定义控件时,我需要将AllowDrop属性设置为true。我最初使用了以下代码,但发现从未触发Drop事件: EditorVisual.cs public class EditorVisual : Control { static EditorVisual() { DefaultStyleKeyProperty.OverrideMetadata(typeof(EditorVisual), new Framework

在制作一个用作拖放目标的自定义控件时,我需要将
AllowDrop
属性设置为
true
。我最初使用了以下代码,但发现从未触发
Drop
事件:

EditorVisual.cs

public class EditorVisual : Control
{
    static EditorVisual()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(EditorVisual),
            new FrameworkPropertyMetadata(typeof(EditorVisual)));
        AllowDropProperty.OverrideMetadata(typeof(EditorVisual),
            new FrameworkPropertyMetadata(true));
    }
    // ...
    protected override void OnDrop(DragEventArgs e)
    {
        base.OnDrop(e);
        // this is never called
    }
}
Themes/Generic.xaml

<Style TargetType="{x:Type local:EditorVisual}">
    <Setter Property="Background" Value="LightGreen" />
    <!-- Uncomment to make things work -->
    <!-- <Setter Property="AllowDrop" Value="True" /> -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:EditorVisual}">
                <Border Background="{TemplateBinding Background}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>    

最后,我将它缩小到设置
AllowDrop
属性的方式。将其设置为xaml或默认样式可以使一切正常工作。。。这让我很困惑。为什么使用元数据覆盖不足以在自定义控件中接收拖放事件


编辑:在Windows 8上使用Visual Studio 2012和.Net 4.0在任何CPU上进行测试-调试。

好的,我现在了解您是如何测试它的

事实上,若您希望使拖放工作正常,则需要将AllowDrop设置为true。但是AllowDrop是一个允许继承标志的框架属性,因此为什么ControlTemplate中的所有控件都将AllowDrop设置为true

现在,在WPF中,您不能覆盖支持inherits标志的框架属性的元数据。当您这样做时,您将终止继承的属性

你有两种可能解决这个问题

  • 在构造函数中设置值:

    公共编辑器Visual() { this.AllowDrop=true; }

  • 在样式中设置值(这是您已经拥有的)


  • 静态构造函数不能工作的原因是
    AllowDrop
    是继承的依赖属性。当您更改
    EditorVisual
    控件的默认值时,它不会将该值向下传播到可视化树,这意味着您提供的模板中的控件仍将
    AllowDrop
    设置为
    false
    。拖放期间的命中测试遇到这些控件并失败


    使用样式设置此值(或在控件的实例构造函数中)是完全可以的。

    您是如何测试此值的?只要看看你的代码,我就知道在代码或xaml中将AllowDrop设置为true是行不通的。顺便说一句,使用OverrideMetadata或Style.Setter并不重要。您将需要重写/写入控件中的其他几个方法,以使拖放工作正常。你能告诉我们这些方法吗?看看这个链接:@devhedgehog,是的,我已经测试过了。虽然您可以覆盖
    OnDragEnter
    和其他工具来增强体验,但最低要求是
    AllowDrop=true
    和覆盖
    OnDrop
    。请参阅msdn:您是如何测试它的?@devhedgehog,使用visual studio,通过使用调试器运行它。从测试应用程序内以及从
    explorer
    拖动多个对象。无论采用何种方法,事件的
    OnDrag*
    系列都是通过样式设置的
    AllowDrop
    调用的,而不是通过覆盖。