Enter null values from ComboBox

A

Andrus

I need to enter null value from combobox to business object property.

My combobox datasource does not contain ValueMember with null value.
So I tried to create combobox which stores null to bound object when text is
deleted.
However bound object contains old value in this case.

To reproduce:

1. Run code
2. Delete Walter from ComboBox
3. Click button

Observed:

s.CustId contains W

Expected:

s.CustId must be null

How to fix ?

Andrus


using System.Windows.Forms;
using System.Collections.Generic;

class testForm : Form {
Storage s = new Storage();

testForm() {
Customer c = new Customer();
c.Id = "J";
c.Name = "John";
List<Customer> l = new List<Customer>();
l.Add(c);

c = new Customer();
c.Id = "W";
c.Name = "Walter";
l.Add(c);

ComboBox cm = new ComboBox();
cm.DisplayMember = "Name";
cm.ValueMember = "Id";
cm.DataSource = l;

s.CustId = "W";
cm.DataBindings.Add("SelectedValue", s, "CustId");
Controls.Add(cm);

Button b = new Button();
b.Top = 80;
b.Click += new System.EventHandler(b_Click);
Controls.Add(b);
}

void b_Click(object sender, System.EventArgs e) {

if (s.CustId == null)
MessageBox.Show("Empty combobox must store null value");
else
MessageBox.Show(s.CustId.ToString());
}

class Customer {
public string Id { get; set; }
public string Name { get; set; }
}

class Storage {
public string CustId { get; set; }
}

static void Main() {
Application.Run(new testForm());
}
}
 
M

Morten Wennevik [C# MVP]

Hi Andrus,

What are you ultimatly trying to achieve? You have bound the item list to
one source another to keep track of the selected value, but since
DropDownStyle is set to DropDown, anything you write in the edit box does not
update the list. It merely changes the Text property.

It is possible to add a databinding between Name and Text to force an update
of the business object, but a ComboBox really isn't suited for changing the
object, and databinding a ComboBox with edit box enabled leads to more
frustration than it is worth.

If you want to delete an item, you should not delete anything from the Items
list of the ComboBox, but rather from the underlying datasource. To have the
ComboBox update itself you also need to have a BindingSource or a BindingList
which is capable to notifying controls bound to it.

If you want to clear the selected item from storage, you could either use a
button, add a blank item, or handle the KeyDown event and set SelectedIndex
to -1 when [Del] is hit. Beware, that setting SelectedIndex to -1 will send
DBNull.Value to the business object unless you handle parse the databinding.

The easiest solution is just adding a blank item

Customer c = new Customer();
c.Id = null;
c.Name = "<Noone>";
l.Add(c);
 
A

Andrus

Morten,
What are you ultimatly trying to achieve?

I want to create nullable combobox whuch stores null to datasource when Text
is empty and null value is not in ComboBox Item list.
If you want to clear the selected item from storage, you could either use
a
button, add a blank item, or handle the KeyDown event and set
SelectedIndex
to -1 when [Del] is hit. Beware, that setting SelectedIndex to -1 will
send
DBNull.Value to the business object unless you handle parse the
databinding.

I tried the code below but null is not stored to s.CustId.
How to change this code so that null is stored to s.CustId ?
The easiest solution is just adding a blank item

Customer c = new Customer();
c.Id = null;
c.Name = "<Noone>";
l.Add(c);

It it possible to store null without adding null entity to Customer class ?
I have generic ComboBox which allows to select foreign keys from Customer,
Product etc.
lists.
Generic code to instantiate and add null Id to every such objects seems to
be compilated.
In every list Id and Name propetries have different names, eq. names may be
productname, customername, productcode, customervatno etc.
So I must use CreateInstance to create empty entity object and then use
reflection to set id property to null and foreign key property to empty
string.
This seems to be complicated. So I'm looking for a simpler way to allow
Combobox natively support this.

Andrus.


using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;

class testForm : Form {

Storage s = new Storage();

testForm() {

Customer c = new Customer();
c.Id = "J";
c.Name = "John";
List<Customer> l = new List<Customer>();
l.Add(c);

NullableComBobox cm = new NullableComBobox();
cm.DisplayMember = "Name";
cm.ValueMember = "Id";
cm.DataSource = l;

s.CustId = "J";
cm.DataBindings.Add("SelectedValue", s, "CustId");

Controls.Add(cm);
Button b = new Button();
b.Top = 80;
b.Click += new System.EventHandler(b_Click);
Controls.Add(b);
}

void b_Click(object sender, System.EventArgs e) {

if (s.CustId == null)
MessageBox.Show("Value is null");
else
MessageBox.Show("Value is NOT null "+s.CustId.ToString());
}

class Customer {
public string Id { get; set; }
public string Name { get; set; }
}

class Storage {
public string CustId { get; set; }
}

static void Main() {
Application.Run(new testForm());
}
}

/// <summary>
/// Combobx which stores null value for empty Text.
/// </summary>

public class NullableComBobox : ComboBox {

protected override void OnValidating(CancelEventArgs e) {

if (Text.Trim().Length == 0) {
SelectedIndex = -1;
base.OnValidating(e);
return;
}

int pos = FindString(Text.Trim());

if (pos >= 0) {
SelectedIndex = pos;
base.OnValidating(e);
return;
}

e.Cancel = true;
MessageBox.Show("Invalid entry");
base.OnValidating(e);
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top