MVVM共享属性
本文关键字:属性 共享 MVVM | 更新日期: 2023-09-27 17:59:04
SO上也有一些类似的问题,但它们并不完全一样,所以我改为发布这篇文章。我是MVVM的新手,所以我想知道如何创建一个类,该类可以包含可以在视图之间共享的属性。因此,如果我在一个视图中设置了一个属性,那么如果它发生了更改,所有其他视图都会收到通知,并相应地调整它们的属性。
我现在拥有的东西相当粗糙,绝对不是我想用的东西。这是我的公共类,它将包含所有属性:
public static class Common
{
private static string _title;
public static string Title
{
get { return _title; }
set
{
if (_title == value)
{
return;
}
_title = value;
OnPropertyChanged("Title");
}
}
public static void Load()
{
// set properties here
}
public static event PropertyChangedEventHandler PropertyChanged;
private static void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(typeof(SettingsWorker), new PropertyChangedEventArgs(name));
}
}
}
我必须从每个ViewModel订阅它:
Common.PropertyChanged += Common_PropertyChanged;
private void Common_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Title = Common.Title;
}
但这就是崩溃发生的地方。我可以从PropertyChangedEventArgs
中获取属性名称,但我不知道如何获取值。因此,我不得不更新所有的属性,这可能会让维护变得很麻烦。代码变得一团糟。
我基本上是在尝试获得ViewModels可以共享的属性。我怎样才能做到这一点?
看起来您只需要在多个位置显示一些全局数据。要做到这一点,最简单的方法是让它像普通的ViewModel类,然后让它对其他每个ViewModel都可用,并从它们中公开它以直接绑定到(而不是将属性复制到每个ViewModel中)。你可以使用IOC来实现这一点,或者使其静态可用,更类似于你现在的方式。
如果您采用静态方向,则需要进行的关键更改是使用singleton而不是静态类,以便允许属性更改通知工作。绑定可在实例上使用INPC,但不能在静态类上使用。Common类看起来更像这样:
public class Common : INotifyPropertyChanged
{
private static Common _instance = null;
protected Common()
{
}
public static Common GetInstance()
{
if (_instance == null)
_instance = new Common();
return _instance;
}
private string _title;
public string Title
{
get { return _title; }
set
{
if (_title == value)
return;
_title = value;
OnPropertyChanged("Title");
}
}
public void Load()
{
}
public virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName);
if (PropertyChanged != null)
PropertyChanged(this, ea);
}
public event PropertyChangedEventHandler PropertyChanged;
}
有很多不同的方法可以使用它。这里有一个更直接的:
public class SomeViewModel : ViewModelBase
{
public Common CommonData { get; private set; }
public SomeViewModel()
{
CommonData = Common.GetInstance();
}
}
然后在XAML中,您可以绑定到公共类的属性并获得更改通知,即使是在不同的VM使用中也是如此。
<TextBox Text="{Binding Path=CommonData.Title}"/>
还有一种选择是将singleton作为属性进行访问,并使用x:Static从XAML直接绑定到它,但这与您所要求的方向有点不同。
因此,如果您有其他视图希望在属性更改时得到通知,我假设您为每个视图都有一个单独的视图模型。在这种情况下,你会问"视图模型如何与其他视图模型对话?"为了获得良好的学习体验,我建议研究观察者模式。如果你不喜欢这种风格,那么我建议你考虑使用MVVM框架,比如"SimpleMVVM、Catel或许多其他"(只需要查找一些)。然后,一旦你的项目中有了这个框架,我就会创建一个基本的视图模型类,所有的视图模型都将继承这个类。一旦完成,您就可以利用框架信使系统。基本上它看起来像:
public YourViewModel()
{
RegisterToReceiveMessages(MessageTokens.SomeToken, OnChangeCallYourMethodToAddress); //The MessageTokens is something you generally create ur self.
}
#region Notifications
void OnChangeCallYourMethodToAddress(object sender, NotificationEventArgs<SlideShowLocale> e)
{
SomeProperty = e.Data;
}
然后从另一个ViewModel向"YourViewModel"发送消息:
public AnotherViewModel
{
SendMessage(MessageTokens.SomeToken, new NotificationEventArgs(WhateverYouWantToSend));
}
因此,基本上,通过声明您想要的令牌,它会找到用该令牌注册的视图模型,并侦听任何传入的消息