【发布时间】:2017-11-25 14:08:44
【问题描述】:
我刚开始使用 MVVM 设计模式,并根据此 youtube 视频 https://www.youtube.com/watch?v=EpGvqVtSYjs 中显示的示例构建了自己的小项目,源代码可在此处找到 http://danderson.io/posts/mvvm-session-01-02-demo-source-code-downloads/。除了示例之外,我还在模型中创建了一个新线程,它每秒更新一些模型属性。它运作良好;我的视图中的文本框像预期的那样每秒更新一次。但是,示例在模型上实现了 INotifyPropertyChanged,并且从视图绑定到模型的属性。如果我正确理解了 MVVM 模式,后一种描述的方法是针对 MVVM 模式的,INotifyPropertyChanged 应该在 ViewModel 上实现,而 View 应该绑定到 ViewModel 中的属性。这正是我在我的小项目上尝试过的,但我不知道 ViewModel 应该如何知道模型的属性是否已更新以将 PropertyChanged 事件抛出给 View。模型、视图模型和视图绑定代码的代码粘贴在下面。非常欢迎任何关于我的奋斗的想法,提前谢谢。
模型类:
public class Customer
{
private Thread _thread;
/// <summary>
/// Initializes a new instance of the Customer class.
/// </summary>
public Customer() {
_thread = new Thread(Temporal);
_thread.IsBackground = true;
_thread.Start();
}
private string _Name;
/// <summary>
/// Gets or sets the Customer's name.
/// </summary>
public String Name {
get {
return _Name;
}
set {
_Name = value;
}
}
public void Temporal()
{
int i = 0;
while (true)
{
Name = "Customer #" + i.ToString();
i++;
System.Threading.Thread.Sleep(1000);
}
}
}
ViewModel 类:
internal class CustomerViewModel : INotifyPropertyChanged
{
/// <summary>
/// Initializes a new instance of the CustomerViewModel class.
/// </summary>
public CustomerViewModel() {
_Customer = new Customer();
}
private Customer _Customer;
public string Name
{
get { return _Customer.Name }
set
{
_Customer.Name = value;
OnPropertyChanged("Name");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
对于我的视图中的绑定,我使用以下内容:
Text="{Binding CustomerViewModel.Name, UpdateSourceTrigger=PropertyChanged}"
【问题讨论】:
-
在哪里实现 INotifyPropertyChanged 并不重要。它在模型和视图模型中都有效。也就是说,最好使用
DispatcherTimer进行重复操作,而不是生成线程。最后,设置UpdateSourceTrigger=PropertyChanged对您的绑定没有影响。它只控制 TwoWay 或 OneWayToSource 绑定如何更新其源属性。一个常见的误解是它与 INotifyPropertyChanged 接口的 PropertyChanged 事件有关。 -
我闻到你在装订的地方有问题。 @Clemens 所说的同上,但你的绑定不应该是:
Text="{Binding Name}",而不是在它前面加上CustomerViewModel。您要绑定的属性名称与您正在使用的上下文相关,因此您无需输入视图模型的名称。 -
我会考虑更新您的问题,以便更清楚地了解您实际想要实现的目标。据我所知,您希望每秒更新客户的姓名。如果是这种情况,我会看两种方法中的一种:从 ViewModel 对客户进行更新(并通知更改);或使用某种消息/事件模式从客户那里进行更新,并通知 ViewModel 以这种方式更新。另一个有用的约定是将
private成员的名称设为camelCase(个人偏好以_开头。希望这会有所帮助。 -
感谢大家的反馈。这真的帮助了我前进。