OverrideMetadata和默认样式之间的区别

时间:2013-09-29 03:07:32

标签: c# wpf

在制作充当拖放目标的自定义控件时,我需要将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
    }
}

主题/ 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在任何CPU上使用.Net 4.0进行测试 - 调试。

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

好的我现在明白你是怎么试试的。

事实上,如果你想进行拖放工作,你需要将AllowDrop设置为true。但AllowDrop是一个框架属性,它允许继承标志,因此为什么ControlTemplate中的所有控件都将其AllowDrop设置为true。

现在,事情是在WPF中,您无法覆盖支持继承标志的框架属性的元数据。当你这样做时,你会杀死继承的属性。

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

  1. 在构造函数中设置值:

    public EditorVisual() {   this.AllowDrop = true; }

  2. 设置样式中的值(这是您已经拥有的)。