Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Databinding TextBox to integer property in another object

I have what I think is a very simple databinding question (I'm still new to WPF). I have a class (simplified for this question)

public class ConfigurationData
{
    public int BaudRate { get; set; } 
}

In MainWindow.Xaml.cs I have a private member variable:

private ConfigurationData m_data;

and a method

void DoStuff()
{
   // do a bunch of stuff (read serial port?) which may result in calling...
   m_data.BaudRate = 300; // or some other value depending on logic
}

In my MainWindow gui, I'd like to have a TextBox that displays m_data.BaudRate AND allows for two way binding. The user should be able to enter a value in the textbox, and the textbox should display new values that we're caused by "DoStuff()" method. I've seen tons of examples on binding to another property of a control on MainWindow, and binding to a datacollection, but no examples of binding to a property of another object. I would think that my example is about as simple as it get, with the nagging annoyance that I'm binding to an integer, not a string, and if possible, I would like the user to only be able to enter integers.
BTW I considered using a numeric up/down, but decided against it as there did not seem to be a lot of support/examples of non-commercial numeric up/down controls. Plus, it could be an awfully big range of numbers to spin through.

I think a pointer to one good example would get me on my way. Many thanks in advance, Dave

like image 768
Dave Avatar asked Oct 07 '10 21:10

Dave


1 Answers

Although this question is old, it's a good one, and is rarely answered succinctly. Let me offer a simplified solution for others who come upon this page.

In order to support two-way binding, your initial ConfigurationData class must be expanded to support property changes. Otherwise the changes in DoStuff() will not be reflected in the UI textbox. Here is a typical way of doing that:

using System.ComponentModel;
public class ConfigurationData : INotifyPropertyChanged
{
    private int _BaudRate;
    public int BaudRate
    {
        get { return _BaudRate; }
        set { _BaudRate = value; OnPropertyChanged("BaudRate"); }
    }

    //below is the boilerplate code supporting PropertyChanged events:
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

I choose to put the textbox binding right in the XAML (I've also added a button to DoStuff), like so:

<Canvas>
    <TextBox Width="96" Name="textBox1" Text="{Binding BaudRate}" />
    <Button  Width="96" Canvas.Top="25" Content="ChangeNumber" Click="DoStuff"/>
</Canvas>

The tricky part is gluing this all together. For that you'll need to define your DataContext. I prefer to do this in the constructor of my main window. Here's the code:

public partial class MainWindow : Window
{
    private ConfigurationData m_data;
    public MainWindow()
    {
        InitializeComponent();
        m_data = new ConfigurationData();
        this.DataContext = m_data;  // This is the glue that connects the
                                    // textbox to the object instance
    }

    private void DoStuff(object sender, RoutedEventArgs e)
    {
        m_data.BaudRate += 300;
    }
}
like image 82
kmote Avatar answered Oct 12 '22 00:10

kmote