我想创建一个只读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();
}
}
答案 0 :(得分:0)
因此,在试图找到一个更好的解决方案近一年后,似乎我的反射方法仍然是最好的解决方案。