I just started with the MVVM design pattern and built my own small project based on the example shown in this youtube video https://www.youtube.com/watch?v=EpGvqVtSYjs, source is found here http://danderson.io/posts/mvvm-session-01-02-demo-source-code-downloads/. In addition to the example I created a new thread in the Model which updates some of the Model properties every second. It worked well; the text boxes in my View were updated every second like expected. However, the example implemented INotifyPropertyChanged on the Model and bindings were made from the View to the properties of the Model. If I understood the MVVM pattern corretly, the latter described approach is against the MVVM pattern, the INotifyPropertyChanged should be implemented on the ViewModel instead and the View should bind to the properties which are in the ViewModel. And that is exactly what I tried on my small project, but I have no idea how the ViewModel should know whether the Properties of the Model are updated to throw the PropertyChanged event to the View. The code of the Model, ViewModel and the View binding code is pasted below. Any idea's on my struggle a very much welcome, thanks in advance.
The Model class:
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);
}
}
}
The ViewModel class:
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
}
For the binding in my View I use the following:
Text="{Binding CustomerViewModel.Name, UpdateSourceTrigger=PropertyChanged}"
DispatcherTimer
for a repeated action, instead of spawning a Thread. Finally, settingUpdateSourceTrigger=PropertyChanged
has no effect on your Binding. It only controls how a TwoWay or OneWayToSource Binding updates its source property. It is a common misunderstanding that it has something to do with the PropertyChanged event of the INotifyPropertyChanged interface. – ClemensText="{Binding Name}"
, rather than preceding it withCustomerViewModel
. The property name you're binding to is relative to the context you're using, so you don't need to put the view model's name. – Geoff Jamesprivate
members' namescamelCase
(personal preference to precede with the_
. Hope this helps. – Geoff James