Showing posts with label DataBinding. Show all posts
Showing posts with label DataBinding. Show all posts

Tuesday, December 7, 2010

Custom Binding with INotifyPropertyChanged Interface

Introduction

In this post I would like to show a simple example of using INotifyPropertyChanged interface for binding a custom object properties to WinForm controls.

According to Microsoft's documentation INotifyPropertyChanged interface is used to notify clients about properties value changes.

The underneath idea is very simple: implementing this interface, forces raising PropertyChange event, which in-turn notifies client that binded property has changed.

The Example

Let's start with building a simple BankAccount class :



public class BankAccount : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private decimal m_Balance;
private decimal m_CreditLimit;

public BankAccount(decimal initialBalance)
{
this.m_Balance = initialBalance;
this.m_CreditLimit = initialBalance * 2;
}

public decimal Balance
{
get { return m_Balance; }
}

public decimal CreditLimit
{
get { return m_CreditLimit; }
}

public void Withdrawal(decimal sum)
{
if (sum <= m_Balance)
{
m_Balance -= sum;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("Balance"));
}
}
}

public void Deposit(decimal sum)
{
if (sum > 0)
{
m_Balance += sum;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("Balance"));
}

if(m_Balance >= m_CreditLimit)
{
m_CreditLimit = m_Balance * 2;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("CreditLimit"));
}
}
}
}

}

The class contains two properties "Balance" and "CreditLimit" which are going to be binded to our simple UI elements:



Here is the code demonstrating how we actually bind it:


public partial class MainForm : Form
{
private BankAccount m_Account;

public MainForm()
{
InitializeComponent();
m_Account = new BankAccount(1000);

BindControls();
}

private void BindControls()
{
txtBalance.DataBindings.Add("Text",
m_Account,
"Balance",
true,
DataSourceUpdateMode.OnPropertyChanged);

txtCreditLimit.DataBindings.Add("Text",
m_Account,
"CreditLimit",
true,
DataSourceUpdateMode.OnPropertyChanged);
}

private void btnWithdrawal_Click(object sender, EventArgs e)
{
m_Account.Withdrawal(decimal.Parse(txtSum.Text));
}

private void btnDeposit_Click(object sender, EventArgs e)
{
m_Account.Deposit(decimal.Parse(txtSum.Text));
}
}


Now, the binded textboxes will automatically reflect changes of "Balance" and "CreditLimit" properties after calling Withdrawal/Deposit methods:




The working example could be downloaded here.

This is it,

Mark

Tuesday, October 20, 2009

Automatic Setting of MaxLength Property for Binded Controls

Following example demonstrates smart setting of textBox's MaxLength property, according to the length of binded data source field.
It might be useful in order to prevent exceptions, caused by entering a text, which exceeds specified maximum field size within your data source.
All you should do is to subscribe to DataBindings.CollectionChanged event of your control and put this simple code:

private void DataBindings_CollectionChanged(object sender, CollectionChangeEventArgs e)
{
if (e != null && e.Action == CollectionChangeAction.Add)
{
int bindedFieldMaxLength = this.MaxLength;
Binding bindingObj = (e.Element as Binding);
if (bindingObj != null)
{
if (bindingObj.DataSource != null &&
bindingObj.BindingMemberInfo != null)
{
DataTable sourceTable = (bindingObj.DataSource as DataTable);
DataView sourceView = (bindingObj.DataSource as DataView);
BindingMemberInfo bindingMemberInfoObj =
bindingObj.BindingMemberInfo;
if ((sourceTable != null sourceView != null) &&
bindingMemberInfoObj != null)
{
string bindedFieldName = bindingMemberInfoObj.BindingField;
if (!string.IsNullOrEmpty(bindedFieldName))
{
if ( sourceTable != null &&
sourceTable.Columns[bindedFieldName].MaxLength > 0)
{
bindedFieldMaxLength =
sourceTable.Columns[bindedFieldName].MaxLength;
}
if(sourceView != null &&
sourceView.Table.Columns[bindedFieldName].MaxLength > 0)
{
bindedFieldMaxLength =
sourceView.Table.Columns[bindedFieldName].MaxLength;
}
if (this.MaxLength != bindedFieldMaxLength)
{
this.MaxLength = bindedFieldMaxLength;
}
}
}
}
}
}


That's it...