- understand the concept and the utility of data binding;
- understand the differences between simple and complex data binding;
- implement simple data binding;
- implement complex data binding;
Data binding types
Type | Description |
---|---|
Simple data binding | The ability of a control to bind to a single data element, such as a value in a column in a dataset table. This is the type of binding typical for controls such as a TextBox control or Label control, which are controls that typically only displays a single value. In fact, any property on a control can be bound to a field in a database. |
Complex data binding | The ability of a control to bind to more than one data element, typically more than one record in a database. Complex binding is also called list-based binding. Examples of controls that support complex binding are the DataGridView, ListBox, and ComboBox controls. |
Change notification
- Ensures that your data source and bound controls always have the most recent data, we must add change notification for data binding. Specifically, we want to ensure that bound controls are notified of changes that were made to their data source, and the data source is notified of changes that were made to the bound properties of a control.
Cases:
- Simple Binding – INotifyPropertyChanged
- Complex data binding - IBindingList
Activity
Full source code available, check the
DataBindingSample
sample.
-
Create a copy of the "ListViewBasicSample" project and name it "DataBindingSample"
-
Replace the “ListView” control with a
DataGridView
control (Name:dgvParticipants
) -
Add a “ViewModel” folder to your project
-
Add the following
MainFormViewModel
class in the “ViewModel” folderinternal class MainFormViewModel : INotifyPropertyChanged { #region Properties #region LastName private string _lastName; public string LastName { get { return _lastName; } set { if (_lastName == value) return; _lastName = value; //If we use [CallerMemberName] in the OnPropertyChanged method //OnPropertyChanged(); //If we don't use the [CallerMemberName] in the OnPropertyChanged method OnPropertyChanged("LastName"); } } #endregion #region FirstName private string _firstName; public string FirstName { get { return _firstName; } set { if (_firstName == value) return; _firstName = value; OnPropertyChanged(); } } #endregion #region BirthDate private DateTime _birthDate; public DateTime BirthDate { get { return _birthDate; } set { if (_birthDate == value) return; _birthDate = value; OnPropertyChanged(); } } #endregion public BindingList<Participant> Participants { get; set; } #endregion public MainFormViewModel() { Participants = new BindingList<Participant>(); BirthDate = DateTime.Now; } #region Methods public void AddParticipant() { Participants.Add(new Participant(LastName, FirstName, BirthDate)); LastName = FirstName = string.Empty; BirthDate = DateTime.Today; } #endregion #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; // [CallerMemberName] - Allows you to obtain the method or property name of the caller to the method. https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute%28v=vs.110%29.aspx protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { if(PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #endregion }
-
Modify the
MainForm
class as follows.public partial class MainForm : Form { private readonly MainFormViewModel _viewModel; public MainForm() { InitializeComponent(); _viewModel = new MainFormViewModel(); } private void btnAdd_Click(object sender, EventArgs e) { _viewModel.AddParticipant(); } }
-
Handle the
Load
event of theMainForm
as follows.private void MainForm_Load(object sender, EventArgs e) { dgvParticipants.DataSource = _viewModel.Participants; //tbLastName.DataBindings.Add("Text", _viewModel, "LastName"); //Recommended (without magic strings): tbLastName.DataBindings.Add("Text", _viewModel, nameof(MainFormViewModel.LastName)); tbFirstName.DataBindings.Add("Text", _viewModel, "FirstName"); dtpBirthDate.DataBindings.Add("Value", _viewModel, "BirthDate"); }
Further reading about the MVVM pattern: https://msdn.microsoft.com/en-us/library/hh848246.aspx
Assignments (for you to try) 🎮
-
Add a button to the
MainForm
that will allow the user to delete the currently selected participant.Hint: you can use the
DataBoundItem
property in order to identify the participant corresponding to the currently selected row.For the complete sample, check the
DataBindingSample
project in the "code samples" folder. -
Add a button to the
MainForm
that will allow the user to edit the currently selected participant using a secondary form (ex:EditForm
).
Documentation:
Activity
Full source code available, check the
DataBindingSample.Tests
sample.
-
Add a new
Unit Test
project. -
Add a reference to the project created above.
-
Let's test that the
AddParticipant()
method implemented above is actually adding a participant.[TestClass] public class MainFormViewModelUnitTest { [TestMethod] public void AddParticipantTestMethod() { //Unit testing basics: https://msdn.microsoft.com/en-us/library/hh694602.aspx // arrange var viewModel = new MainFormViewModel(); // act viewModel.AddParticipant(); // assert Assert.AreEqual(viewModel.Participants.Count, 1); } }
Assignments (for you to try) 🎮
- Implement additional unit test methods (ex: check whether the
LastName
property of the added participant is correct).
- MVVM Pattern: https://msdn.microsoft.com/en-us/library/hh848246.aspx
- Unit Testing: https://msdn.microsoft.com/en-us/library/hh694602.aspx