覆盖FrameworkPropertyMetadata中的DefaultTwoWayByDefault

时间:2016-12-13 09:04:28

标签: c# wpf

我想创建一个只读TextBox,它的Text属性上有一个默认的OneWay Binding。 就像very similar question中的第一次尝试一样:

public partial class SelectableTextBlock : TextBox
{
    static SelectableTextBlock ()
    {
        TextBox.TextProperty.OverrideMetadata(typeof(ReadOnlyTextBox), 
            new FrameworkPropertyMetadata() { BindsTwoWayByDefault = false, Journal = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.Explicit }); 
    }
    public SelectableTextBlock()
    {
        InitializeComponent();
    }
}

我发现这不起作用,因为WPF通过基本上将所有标志OR化在一起来组合现有元数据和覆盖元数据。 由于BindsTwoWayByDefault是其中一个标志,只要其中一个元数据对象具有BindsTwoWayByDefault = true就保持为真。

唯一的方法是在OverrideMetadata中进行WPF合并过程后更改元数据。 但是,元数据对象在方法中标记为“密封”。

任何优秀的开发者都会在这里停下来重新考虑...... Naaa,我用反射来开启"开封#34;元数据对象并将BindsTwoWayByDefault设置为true。

请告诉我,我很愚蠢,并没有看到在WPF中这样做的明显和正确的方法。

这是我的代码:

public partial class SelectableTextBlock : TextBox
{
    static SelectableTextBlock()
    {
        var defaultMetadata = (FrameworkPropertyMetadata)TextProperty.GetMetadata(typeof(TextBox));

        var newMetadata = new FrameworkPropertyMetadata(
            defaultMetadata.DefaultValue,
            FrameworkPropertyMetadataOptions.Journal,
            defaultMetadata.PropertyChangedCallback,
            defaultMetadata.CoerceValueCallback,
            defaultMetadata.IsAnimationProhibited,
            defaultMetadata.DefaultUpdateSourceTrigger);

        TextProperty.OverrideMetadata(typeof(SelectableTextBlock), newMetadata);

        //Workaround for a bug in WPF were the Metadata is merged wrongly and BindsTwoWayByDefault is always true
        var sealedProperty = typeof(PropertyMetadata).GetProperty("Sealed", BindingFlags.Instance | BindingFlags.NonPublic);
        sealedProperty.SetValue(newMetadata, false);
        newMetadata.BindsTwoWayByDefault = false;
        sealedProperty.SetValue(newMetadata, true);
    }

    public SelectableTextBlock()
    {
        InitializeComponent();
    }
}

1 个答案:

答案 0 :(得分:0)

因此,在试图找到一个更好的解决方案近一年后,似乎我的反射方法仍然是最好的解决方案。