【发布时间】:2021-09-13 19:35:50
【问题描述】:
我正在开发一个应用程序并尝试尽可能多地遵循 MVVM,因此有许多具有相应 ViewModes 的视图。我正在反序列化使用 XAML 在视图中实例化的 ViewModel。例如,如果 View 称为“ExampleView”,而 ViewModel 称为“ExampleViewModel”。 ViewModel 通过这样做在 ExampleView 中实例化...
<UserControl.Resources>
<local:ExampleViewModel x:Key="ViewModel" />
</UserControl.Resources>
使用后面的代码从 View 中获取/设置 ViewModel(通常这只是一个获取,但我尝试在反序列化后设置 ViewModel)。
public ExampleViewModel ViewModel
{
get { return (ExampleViewModel)this.Resources["ViewModel"]; }
set
{
if (this.Resources["ViewModel"]!=value)
{
this.Resources["ViewModel"] = value;
}
}
}
这不起作用,但我认为原因是 PropertyChanged 没有被解雇。因此,在 ExampleViewModel 中,我输入了一种方法来刷新每个属性。比如……
public void RefreshAllProperties()
{
NotifyPropertyChanged("Property1");
NotifyPropertyChanged("Property2");
...
}
NotifyPropertyChanged 在哪里...
private void NotifyPropertyChanged([CallerMemberName] string PropertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
虽然这没有通过代码气味测试,但我试图在寻找更优雅的方法的过程中理解。但是,我惊讶地发现它不起作用。
我更愿意在 XAML 中实例化 ViewModel。是否有在反序列化后重新实例化 ViewModel 的最佳做法?
修改了后续问题
关于将创建的 ViewModel 移动到 View 类的构造函数中的任何 cmets?这是更好的设计模式吗?
ExampleViewModel exampleViewModel;
public ExampleView()
{
InitializeComponent();
ExampleViewModel = new ExampleViewModel();
this.DataContext = ExampleViewModel;
}
public ExampleViewModel ViewModel
{
get { return exampleViewModel; }
set
{
if (exampleViewModel!=value)
{
exampleViewModel = value;
NotifyPropertyChanged();
}
}
}
【问题讨论】:
-
这一切有什么用? UserControl 通常会在由其 DataContext 属性的属性值继承提供的视图模型实例上进行操作。
-
如果您在运行时更改资源的值,您需要通过
{DynamicResource}标记扩展来引用它。不是{StaticResource}。静态资源仅在加载时读取一次。 INotifyPropertyChanged 在任何一种情况下都无济于事。因为资源不是属性。 -
如何绑定到资源中声明的虚拟机实例?