WPF Databinding TextBox for an integer property in another object

I have what I consider to be a very simple data binding issue (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 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 would like to have a TextBox that displays m_data.BaudRate AND allows two-way binding. The user should be able to enter a value in the text box, and the text box should display the new values โ€‹โ€‹invoked by the DoStuff () method. I saw many examples of binding to another property of the MainWindow control and binding to a datacollection, but not examples of binding to the property of another object. I would think that my example is about as simple as he is, with a sarcastic annoyance that I am attached to an integer, not a string, and, if possible, I would like the user to be able to enter only integers.
BTW I thought I was using an up / down number, but decided against it, since there did not seem to be much support / examples of non-commercial numeric up / down controls. In addition, it can be a terribly large range of numbers to scroll through.

I think a pointer to one good example will make me go. Thanks in advance, Dave

+4
source share
3 answers

Although this question is old, it is a good one and it rarely answers succinctly. Let me suggest a simplified solution for others who come to this page.

To support two-way binding, your original ConfigurationData class must be extended to support property changes. Otherwise, changes to DoStuff() will not be displayed in the text box of the user interface. Here is a typical way to do this:

 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 want to set the binding of a text field directly in XAML (I also added a DoStuff button), for example:

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

The hard part is gluing it all together. To do this, you will need to define your DataContext. I prefer to do this in the constructor of my main window. Here is 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; } } 
+16
source

I'm sure there is a better way (please tell me!), But here one way that I combined works. There seems to be a simpler way. For the BaudRate property, use:

 public int BaudRate { get { return m_baudRate; } set { if (value != m_baudRate) { m_baudRate = value; OnPropertyChanged("BaudRate");//OnPropertyChanged definition left out here, but it pretty standard } } } 

For XAML, I don't have significant markup:

 <TextBox Height="23" Margin="137,70,21,0" Name="textBox1" VerticalAlignment="Top" /> 

Now this is the dirty part ... Create a class to test:

 public class IntRangeRule : ValidationRule { // See ValidationRule Class public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { try { if (value is int) // replace with your own logic or more robust handling... { return new ValidationResult(true, "Fine"); } else { return new ValidationResult(false, "Illegal characters or "); } } catch (Exception e) { return new ValidationResult(false, "Illegal characters or " + e.Message); } } } 

And then in the constructor of Window1 (MainWindow):

 Binding myBinding = new Binding("BaudRate"); myBinding.NotifyOnValidationError = true; myBinding.Mode = BindingMode.TwoWay; ValidationRule rule = new IntRangeRule(); myBinding.ValidationRules.Add(rule); myBinding.Source = m_data; // where m_data is the member variable of type ConfigurationData textBox1.SetBinding(TextBox.TextProperty, myBinding); 

All my attempts to do everything in the markup failed. The best ways?

Dave

0
source

All Articles