TL; DR: SetCurrentValue
取消设置依赖项属性,如果:
我今天遇到这个问题需要一段时间来修复,但我仍然不明白为什么会发生这种情况,所以我认为这里可能值得一提。我目前认为这是WPF框架中的一个错误。
我有一个控件MyTextBox
,它继承自WPF TextBox。它具有以下文本属性的元数据覆盖:
static MyTextBox()
{
TextProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, null, CoerceText, true, UpdateSourceTrigger.Explicit));
}
CoerceText
方法存在,但不会更改基值:
private static object CoerceText(DependencyObject d, object basevalue)
{
return basevalue;
}
Text
属性没有约束(如果有的话,事情会有效!)
现在假设我执行以下操作:
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
if (e.Key == Key.Enter)
{
var newText = Text;
SetCurrentValue(TextProperty, newText);
}
}
如果我调试此代码,this.Text
在调用""
后变为SetCurrentValue
(空字符串)。但是,它应该保持不变。
我最后通过调试SetCurrentValue
方法(实际上并不是真正的可调试方法......)。
该特定测试失败,来自UpdateEffectiveValue
的{{1}},导致无法取消DP的值。为了自己的理智,我没有再进一步了。
DependencyObject.cs
最后,正如我所说,我修复了问题,解决方法是在重写的元数据中删除我自己的Coerce回调:
if (newEntry.FullValueSource != (FullValueSource) BaseValueSourceInternal.Default)
{
...
}
else
{
UnsetEffectiveValue(entryIndex, dp, metadata);
}
我没有理由解释为什么删除static MyTextBox()
{
TextProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, null, null, true, UpdateSourceTrigger.Explicit));
}
,CoerceValueCallback
按预期工作并保持依赖属性不变而不是清除它。
所以我的问题是,是否有一个明智的解释为什么在这些特定条件下会发生这种行为?