views:

1031

answers:

2

How to bind a TextBox to an integer? For example, binding unit to textBox1.

public partial class Form1 : Form
{
    int unit;

    public Form1()
    {
        InitializeComponent();


    }

    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.DataBindings.Add("Text", unit, "???");
    }
+6  A: 

It would need to be a public property of an instance; in this case, the "this" would suffice:

public int Unit {get;set;}
private void Form1_Load(object sender, EventArgs e)
{
    textBox1.DataBindings.Add("Text", this, "Unit");
}

For two-way notification, you'll need either UnitChanged or INotifyPropertyChanged:

private int unit;
public event EventHandler UnitChanged; // or via the "Events" list
public int Unit {
    get {return unit;}
    set {
        if(value!=unit) {
            unit = value;
            EventHandler handler = UnitChanged;
            if(handler!=null) handler(this,EventArgs.Empty);
        }
    }
}

If you don't want it on the public API, you could wrap it in a hidden type somewhere:

class UnitWrapper {
    public int Unit {get;set;}
}
private UnitWrapper unit = new UnitWrapper();
private void Form1_Load(object sender, EventArgs e)
{
    textBox1.DataBindings.Add("Text", unit, "Unit");
}

For info, the "events list" stuff goes something like:

    private static readonly object UnitChangedKey = new object();
    public event EventHandler UnitChanged
    {
        add {Events.AddHandler(UnitChangedKey, value);}
        remove {Events.AddHandler(UnitChangedKey, value);}
    }
    ...
    EventHandler handler = (EventHandler)Events[UnitChangedKey];
    if (handler != null) handler(this, EventArgs.Empty);
Marc Gravell
+2  A: 

You can use a binding source (see comment). The simplest change is:

public partial class Form1 : Form
{
    public int Unit { get; set; }
    BindingSource form1BindingSource;

    private void Form1_Load (...)
    {
        form1BindingSource.DataSource = this;
        textBox1.DataBindings.Add ("Text", form1BindingSource, "Unit");
    }
}

However, you'll gain some conceptual clarity if you separate out the data a bit:

public partial class Form1 : Form
{
    class MyData {
        public int Unit { get; set; }
    }

    MyData form1Data;
    BindingSource form1BindingSource;

    private void Form1_Load (...)
    {
        form1BindingSource.DataSource = form1Data;
        textBox1.DataBindings.Add ("Text", form1BindingSource, "Unit");
    }
}

HTH. Note access modifiers omitted.

XXXXX
Marc Gravell's change is simpler and seems fine. I'm in the habit of binding everything to BindingSource objects on general principles; it's there, it's built for this purpose, might as well use it.
XXXXX
BindingSource acts purely as a level of abstraction; you can bind directly to both instances and lists.
Marc Gravell
I'm not sure what you mean by *purely* as a level of abstraction; there's actual code in BindingSource that does things, such as manage currency.
XXXXX
Currency is managed by a currency manager, which you get by default when binding to an `IList`/`IListSource`; you simply get *more* control with `BindingSource`. So if you need it, great! `BindingSource` also provides points to control creation of new items for lists, but you can do that in many other ways, including simply implementing the right `ComponentModel` interfaces.
Marc Gravell
Indeed. You get more control, BindingSource is cheap to implement, it's part of the standard framework and built precisely for that purpose. I agree: you don't *have* to use BindingSource, but for the above reasons, my preference is to use it unless there's a compelling reason not to.
XXXXX