16

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, "???");
    }
1
  • 6
    It derives from Form class. Commented Sep 30, 2009 at 11:17

3 Answers 3

23

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);
Sign up to request clarification or add additional context in comments.

4 Comments

Marc, I can't find more info about that trick when you name your event xxxChanged for property xxx and then it is handled behind the scene. Can you post a link or at least how the trick is called? Thanks
That is part of the PropertyDescriptor implementation - basically it looks for a pattern of *Changed events. However, you can also usually use INotifyPropertyChanged
attributes naming trick when xxxAttribute class can be used then as just xxx is well written in msdn. But this behaviour is really hidden. I've tried to google some more info about it but failed (maybe because word 'changed' puzzles search query) :) anyway, thx again
@pkuderov the Attribute thing is a compiler behaviour - the *Changed is applied at runtime. Other ones include things like ShouldSerialize - again this is applied by PropertyDescriptor
5

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.

5 Comments

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.
BindingSource acts purely as a level of abstraction; you can bind directly to both instances and lists.
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.
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.
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.
4

One of the things I like to do is to create "presentation" layer for the form. It is in this layer that I declare the properties that are bound to the controls on the form. In this case, the control is a text box.

In this example I have a form with a textbox to display an IP Address

enter image description here

We now create the binding source through the textbox properties. Select DataBindings->Text. Click the down arrow; select 'Add Project Data Source'.

enter image description here

This starts up that Data Source wizard. Select Object. Hit 'Next'.

enter image description here

Now select the class that has the property that will be bounded to the text box. In this example, I chose PNetworkOptions. Select Finish to end the wizard. The BindingSource will not be created.

enter image description here

The next step is to select the actual property from the bound class. From DataBindings->Text, select the downarrow and select the property name that will be bound to the textbox.

enter image description here

In the class that has your property, INotifyPropertyChanged must implemented for 2-way communication for IP Address field

public class PNetworkOptions : IBaseInterface, INotifyPropertyChanged
{
    private string _IPAddress;


    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public string IPAddress
    {
        get { return _IPAddress; }
        set
        {
            if (value != null && value != _IPAddress)
            {
                _IPAddress = value;
                NotifyPropertyChanged("IPAddress");
            }
        }
    }
}

In the form constructor, we have to specifically define the binding

Binding IPAddressbinding = mskTxtIPAddress.DataBindings.Add("Text", _NetOptions, "IPAddress",true,DataSourceUpdateMode.OnPropertyChanged);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.