用于对嵌套属性进行更改通知的模式
本文关键字:通知 模式 嵌套 属性 用于 | 更新日期: 2023-09-27 18:15:12
我想绑定到我的ViewModel的属性的属性。嵌套对象在编译时是未知的,所以我不能直接将绑定路径设置为它的一个属性。相反,我将对象作为一个整体绑定,然后值转换器使用反射找出感兴趣的属性(或多个属性)。
绑定和值转换器最初工作良好,但如果嵌套属性的值被更改,则不会调用值转换器(如果在VM中更改了对该对象的引用)。VM和嵌套类都实现了INotifyPropertyChanged
。
这里是一个简化的例子,如果Name
的值最初设置为"Bond",则秘密被揭示,但如果组合框的值在程序运行时更改为"Bond",则永远不会泄露:
XAML:
<Window.Resources>
<local:ViewModel x:Key="vm" />
<local:NameToVisConverter x:Key="NameToVis" />
</Window.Resources>
<StackPanel DataContext="{StaticResource vm}">
<ComboBox SelectedValue="{Binding MyPoco.Name}">
<sys:String>Smith</sys:String>
<sys:String>Jones</sys:String>
<sys:String>Bond</sys:String>
</ComboBox>
<Label Visibility="{Binding MyPoco, Converter={StaticResource NameToVis}}">
Secret!
</Label>
</StackPanel>
视图模型,嵌套类:
public class ViewModel : BindableBase
{
public Poco MyPoco
{
get { return _MyPoco; }
set { SetProperty(ref _MyPoco, value); }
}
private Poco _MyPoco = new Poco();
}
public class Poco : BindableBase
{
public String Name
{
get { return _Name; }
set { SetProperty(ref _Name, value); }
}
private String _Name;
}
注: BindableBase
及其SetProperty()
由Prism提供,实现INotifyPropertyChanged
。
来自NameToVisConverter
的值转换方法:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value as Poco).Name == "Bond"
? Visibility.Visible
: Visibility.Collapsed;
}
我天真地认为,如果绑定是在对象本身而不是对象的一个属性上更改了INotifyPropertyChanged
类的属性,那么绑定将会收到警报。显然不是……是否有一个好的模式(或者,希望是一个简单的解决方案)来处理这种情况?
如果我是你,当MyPoco
的任何属性发生变化(或应该被假定已经改变,或无论情况如何)时,我只会让父VM提高PropertyChanged("MyPoco")
。这将导致绑定更新目标,并且将调用转换器的Convert
。
替代方案将涉及您必须编写、调试和维护的c#代码,这是在XAML绑定到不可变的属性值对象的属性或不实现INotifyPropertyChanged
的情况下使用INotifyPropertyChanged
的完美正常方式。例如,我绑定了StringProperty.Length
几次,或者NullableProperty.HasValue
。