Publishing a classic email for public consumption...enjoy!
To All Software Developers and Enthusiasts,
Do you still set model data like this: myModel.Description = textBox1.Text; ?
Do you still populate your UI controls like this: textBox1.Text = myModel.Description; ?
Stop! I’d like to propose a more dynamic way to connect your models with your views. The above type code can make it very difficult to keep your UI and models in sync – especially in large, enterprise-style applications.
Figure 1: Woohoo!!! INotifyPropertyChanged!!! And DataBinding!!!
NOTE: A best practice NOT-covered here is the use of a controller, presenter, or view model. These “middlemen” generally accept a model via some interface and wire it to the UI.
Figure 2
My model is a list of SBUs with the currently selected SBU being determined by the selected index of the shown combo box:
sbuList[sbuUltraComboEditor. SelectedIndex]
This model has a Description property which is databound to the Description text box as follows:
descriptionTextBox. DataBindings.Add("Text", sbuList[sbuUltraComboEditor. SelectedIndex], "Description", false, DataSourceUpdateMode. OnPropertyChanged);
This provides for one-way data binding (view to model).
For demonstration purposes, we will use the Export All button to display the model data (which may or may not correspond to the view data) in a message box and to simulate back-end data changes to the model.
Here is what clicking the Export All button does:
Here is what clicking the Export All button does:
private void exportButton_Click(object sender, EventArgs e)
{
// Show model data.
MessageBox.Show(sbuList[ sbuUltraComboEditor. SelectedIndex].Description);
// Simulate some backend process modifying the model.
sbuList[sbuUltraComboEditor. SelectedIndex].Description = "Gig 'em";
}
Change the view and watch the model change like magic!
In Figure 3, I changed the Description text by typing in the text box “Howdy!”. Clicking the Export All button confirms that the model was updated.
Figure 3
We also know that clicking the button updated the Description property to “Gig ‘em” after displaying the message box. But the UI didn’t update to reflect this change. Clicking the Export All button again confirms the change of the Description property to “Gig ‘em” as shown in Figure 4.
Figure 4
Figure 5: I knew this code the Mad Hatter gave me was not going to work.
But let’s not forget about INotifyPropertyChanged which we can apply to our model to effectively enable two-way data binding. That way when the model is updated, the view will be as well. Here is what INotifyProperty looks like on the model:
public string Description
{
get { return _description; }
set { if (value != _description) _description = value; NotifyPropertyChanged(" Description"); }
}
#region INotifyPropertyChanged Interface
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info) );
}
}
#endregion
Additional Information: http://msdn.microsoft.com/en- us/library/system. componentmodel. inotifypropertychanged.aspx
Figure 6 depicts the functionality after implementing INotifyPropertyChanged instead of the out-of-sync data which was shown in Figure 4. The call to NotifyPropertyChanged notified binding clients that its bound value had been modified and, therefore, needed to update the value.
Figure 6
In summary, by using DataBinding and INotifyPropertyChanged, a two-way data binding solution can be implemented to ensure that views and models will remain in sync.