我想创建一个只读的TextBox,其Text属性具有默认的OneWay绑定。
就像在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通过将所有标志基本或在一起来组合现有元数据和覆盖的元数据。
由于BindsTwoWayByDefault是这些标志之一,因此只要元数据对象之一具有BindsTwoWayByDefault = true,它就保持为true。
解决此问题的唯一方法是在WPF合并过程发生后在OverrideMetadata中更改元数据。
但是,该方法中元数据对象被标记为“已密封”。
作为任何优秀的开发人员,我都会在这里停下来并重新考虑...
不,我使用反射来“解封”元数据对象,并将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();
}
}
最佳答案
因此,在尝试寻找更好的解决方案近一年之后,似乎我的反射解决方案仍然是最好的解决方案。
关于c# - 在FrameworkPropertyMetadata中覆盖DefaultTwoWayByDefault,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41117132/