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.

1 comment:

  1. You could also just throw an exception in the OnSelectedValueChanged event, and then set the Value back to the previous Value in an Exception Handler. You would not need to subclass an entire control with this solution.

    ReplyDelete