我的WPF控件有一个DependencyPropery,它将其值转发给视图模型。该属性绑定到父控件中的视图模型属性(Message.ReceptionState
(。
现在,当源属性(ReceptionState
(更新时,绑定会正确地转发值,但也会在过程中将自己与Message.PropertyChanged
事件分离,因此UI会忽略以下所有更改。绑定肯定设置为单向,但它的行为与一次性模式类似。只有当我将绑定更改为双向时,它才会正常工作。
我检查了.NET源代码,这实际上似乎是预期的行为(请参阅WindowsBase/System/Windows/DependencyObject.cs:742(。若绑定并没有设置为双向,WPF会将值存储在第一个PropertyChanged
上,然后从中分离。但我真的不明白它为什么会这样做。如何告诉UI在不将所有依赖属性更改为双向的情况下继续显示视图模型中的更改?
以下是我的代码的相关部分,以防它有助于澄清问题。我在.NET Core 3.1上使用了一个自制的MVVM框架。
ReceiptStateIndicator.xaml.cs:
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(ReceptionState), typeof(ReceiptStateIndicator), new PropertyMetadata((d, v) =>
{
var indicator = (ReceiptStateIndicator)d;
((ReceiptStateIndicatorVM)indicator.root.DataContext).State = (ReceptionState)v.NewValue;
}));
public ReceptionState State
{
get => (ReceptionState)this.GetValue(StateProperty);
set => this.SetValue(StateProperty, value);
}
ConversationMessage.cs:
private readonly LinkedList<PropertyChangedEventHandler> propertyChanged = new LinkedList<PropertyChangedEventHandler>();
public event PropertyChangedEventHandler PropertyChanged
{
add => propertyChanged.AddLast(value);
remove => propertyChanged.Remove(value); //TODO: event listener is detached after one invocation here!
}
public ReceptionState ReceptionState
{
get => receptionState;
protected set
{
receptionState = value;
foreach (var handler in propertyChanged)
handler?.Invoke(this, new PropertyChangedEventArgs(nameof(ReceptionState)));
}
}
TextChatBubbl.xaml:
<bubbles:ReceiptStateIndicator State="{Binding Message.ReceptionState, Mode=OneWay}"
Width="12" Height="12"
Margin="5 0"
VerticalAlignment="Bottom"
FlowDirection="LeftToRight">
</bubbles:ReceiptStateIndicator>
问题出在更改处理程序的State中。
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(ReceptionState), typeof(ReceiptStateIndicator), new PropertyMetadata((d, v) =>
{
var indicator = (ReceiptStateIndicator)d;
((ReceiptStateIndicatorVM)indicator.root.DataContext).State = (ReceptionState)v.NewValue;
}));
您正在直接写入视图模型属性,该属性正在擦除绑定。
不要这样做。让装订完成它的工作。删除已更改的处理程序上的。