views:

162

answers:

1

Hello,

I've got a problem with getting a ComboBox to operate as expected when data bound, and I am not sure where the problem is.

In the code below, a ComboBox is created and given a data bound list of values, and is then data bound to the form. The idea is that the ComboBox should display the list of options, and when one is selected, it should update the data source, and be indicated in the status text box.

All of this appears to work correctly, except that the ComboBox goes blank after updating the value, which is what I don't understand.

When the data type of the "Selection" property is changed from Int32 to string, it works exactly as expected. As Int32, however, the box goes blank even though it sets the value correctly.

Any help understanding how to fix this problem would be appreciated.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ComboboxDatabindingTest
{
    public partial class Form1 : Form
    {
        ComboBox _box;
        TextBox _status;
        ValuesDataSource _bsValues;
        BindingSource _bsObject;
        Binding _binding;
        int _selection;

        public Form1()
        {
            _selection = 0;

            _bsValues = new ValuesDataSource();

            _bsObject = new BindingSource();
            _bsObject.DataSource = this;

            _status = new TextBox();
            _status.Left = 20;
            _status.Top = 50;
            _status.Width = 200;
            _status.ReadOnly = true;

            _box = new ComboBox();
            _box.Name = "box";
            _box.Left = 20;
            _box.Top = 20;
            _box.Width = 200;
            _box.DropDownStyle = ComboBoxStyle.DropDownList;
            _box.ValueMember = "CodeOrLabel";
            _box.DisplayMember = "Label";
            _box.DataSource = _bsValues;
            _binding = _box.DataBindings.Add("SelectedValue", _bsObject, "Selection");

            this.Controls.Add(_box);
            this.Controls.Add(_status);
        }

        public int Selection
        {
            get { return _selection; }
            set { _selection = value; _status.Text = value.ToString(); }
        }
    }

    public class Value
    {
        private string _code = null;
        private string _label = "";

        public Value(string code, string label)
        {
            _code = code;
            _label = label;
        }

        public string Code
        {
            get { return _code; }
        }

        public string Label
        {
            get { return _label; }
        }

        public string CodeOrLabel
        {
            get { return _code == null ? _label : _code; }
        }
    }

    public class ValuesDataSource : BindingList<Value>
    {
        public ValuesDataSource()
        {
            base.Add(new Value("1", "California"));
            base.Add(new Value("2", "Nevada"));
            base.Add(new Value("3", "Arizona"));
            base.Add(new Value("4", "Oregon"));
        }
    }
}
+1  A: 

It doesn't surprise me that it is struggling. With a SelectedValue binding, it is going to try and find a match (meaning Equals) between the ValueMember of each (i.e. CodeOrLabel) and the bound property (Selection). But it is never true that (for example) "123".Equals(123), so this will never match. So it is presumably deciding that there isn't a selected item (since none match).

Basically, use a string here, or use int throughout.

Marc Gravell
Thank you! I knew it must be a type problem, but I couldn't find it. Solved by making an alias to CodeOrLabel as CodeInt32 and using that as the ValueMember. This allows me to use the same Value objects even when binding to properties of different data types.
Jeremy