我有像这样的ViewModel
Public class AboutPageViewModel
{
public AboutPageViewModel()
{
AppName = Settings.MyAppName;
}
private string _appName;
public string AppName
{
get{return _appName;}
set{_appName = value; RaisePropertyChanged("AppName");}
}
}
现在是静态类
public static class Settings
{
public static string MyAppName{get;set;} = "LOL"
}
每次更改MyAppName时如何通知ViewModel,并将其更新为Binded UI?
谢谢!
答案 0 :(得分:4)
正如您在问题中定义的那样,Settings
不是一个静态类(啊,我在评论中看到这是一个错字,并且它在您的代码中是静态的)。它不应该是静态的。关于静态类的PropertyChanged通知在理论上是可行的,但它不值得花时间去处理,并且没有必要打扰。
让Settings
实施INotifyPropertyChanged
,就像您的viewmodel一样。当MyAppName
更改时,Settings
应该引发PropertyChanged
,就像AboutPageViewModel
在其自己的AppName
属性发生变化时所做的那样。
现在给Settings
一个名为Instance
的静态属性:
public static Settings Instance { get; private set; }
static Settings()
{
Instance = new Settings();
}
并在PropertyChanged
中处理AboutPageViewModel
事件:
public AboutPageViewModel()
{
AppName = Settings.Instance.MyAppName;
Settings.Instance.PropertyChanged += (s,e) =>
{
// If you're in C#6:
//if (e.PropertyName == nameof(Settings.MyAppName))
if (e.PropertyName == "MyAppName")
{
AppName = Settings.Instance.MyAppName;
}
}
}
可以说是一个更好的选择;我不止一次这样做过。
在评论中,@ MikeEason非常清楚这也可以通过*Changed
这样的自定义MyAppNameChanged
事件来完成,这有两个优点:它可以让你回到静态类,它允许您跳过对属性名称的检查,这是额外的代码,也是"magic string"。与INotifyPropertyChanged
合作我们对魔法弦的危险有点麻木,但实际上它们很糟糕。如果你在C#6中,你可以并且绝对应该使用nameof()
运算符,但我们并不是所有人都在C#6中。我在工作中的主要责任是今年夏天我们希望迁移到C#6的应用程序。
public static event EventHandler<String> MyAppNameChanged;
private static String _myAppName = "";
public static String MyAppName {
get { return _myAppName; }
set {
if (_myAppName != value)
{
_myAppName = value;
// C#6 again. Note (thanks OP!) you can't pass this for sender
// in a static property.
MyAppNameChanged?.Invoke(null, value);
}
}
}
这样做的缺点是,这个类称为Settings
,而不是Setting
。也许它有十几个属性在这里和那里发生变化。这可能是一个真正的不同属性改变事件的丛林(&#34;那么什么?&#34;你可能会问 - 你可能有一点意见)。我倾向于坚持PropertyChanged
如果有一大堆它们,并且如果该类只有一个或两个重要属性需要关注,则添加一个事件。在我看来,这两种方式都很烦人;尝试两者,你最终会选择偏好。
答案 1 :(得分:2)
如果你已经在某个地方拥有它,你不需要在ViewModel中存储值(我假设你不会在ViewModel本身改变它):
public class AboutPageViewModel : INotifyPropertyChanged
{
public string AppName => Settings.MyAppName;
}
至于View以了解此属性何时更改,您需要做两件事:1)应该有一种方法在值更改时通知ViewModel 2)上升PropertyChanged(nameof(AppName))
(注意INotifyPropertyChanged
)。
有几种可能性:
Settings
应该在MyAppName
值更改时发生事件,ViewModel订阅并升起PropertyChanged
; INotifyPropertyChanged
的类型,然后绑定到该类型属性,如果该类型上升PropertyChanged
,这将自动更新视图。答案 2 :(得分:0)
您必须在Settings class上实现INotifyPropertyChanged接口!
然后使用相同的代码:
private string _myAppName;
public string MyAppName
{
get{return _myAppName;}
set{_appName = value; RaisePropertyChanged("MyAppName");}
}