Showing posts with label WinForms. Show all posts
Showing posts with label WinForms. Show all posts

Thursday, December 23, 2010

ComboBox SelectedValueChanging Event

Introduction

For some reason, a standard WinForm ComboBox does not contain SelectedValueChanging event, which may be useful if you're requested to intercept a change or cancel it.

After searching for a possible solution on the web, I've found a nice example and adopted it with slight modifications.


SelectedValueChanging Event

Generally, subclassing common WinForm controls is a good idea, since it allows you to customize their appearance and behavior in a single place and affect all instances in the entire application.

In this case, we will subclass a ComboBox class and add the SelectedValueChanging event:


public partial class nessComboBox : ComboBox
{
public event CancelEventHandler SelectedValueChanging;

private object m_LastAcceptedSelectedValue;
private bool m_IgnoreNullPreviousValueChanging = false;

public nessComboBox()
{
InitializeComponent();
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false)]
public object LastAcceptedSelectedValue
{
get { return m_LastAcceptedSelectedValue; }
private set { m_LastAcceptedSelectedValue = value; }
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false)]
public bool IgnoreNullPreviousValueChanging
{
get { return m_IgnoreNullPreviousValueChanging; }
set { m_IgnoreNullPreviousValueChanging = value; }
}

protected void OnSelectedValueChanging(CancelEventArgs e)
{
if (SelectedValueChanging != null)
SelectedValueChanging(this, e);
}

protected override void OnSelectedValueChanged(EventArgs e)
{
if (SelectedValueChanging != null)
{
if ((!m_IgnoreNullPreviousValueChanging ||
LastAcceptedSelectedValue != null) &&
(LastAcceptedSelectedValue ?? string.Empty).ToString()
!= (SelectedValue ?? string.Empty).ToString())
{
CancelEventArgs cancelEventArgs = new CancelEventArgs();
OnSelectedValueChanging(cancelEventArgs);

if (!cancelEventArgs.Cancel)
{
LastAcceptedSelectedValue = SelectedValue;
base.OnSelectedValueChanged(e);
}
else
SelectedValue = LastAcceptedSelectedValue;
}
else if (m_IgnoreNullPreviousValueChanging &&
LastAcceptedSelectedValue == null
&& SelectedValue != null)
{
LastAcceptedSelectedValue = SelectedValue;
}
}
else
{
base.OnSelectedValueChanged(e);
}
}
}


As you can see, the overrided OnSelectedValueChanged method performs all required logic: checks if there are subscribers to the new event and raises it before calling of the OnSelectedValueChanged method.

The variable m_IgnoreNullPreviousValueChanging may be used to ignore the initial selection change from null to some specific value in case of data-binded combo.

That's 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...