WPF 数据绑定文本框到另一个对象中的整数属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3886163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Databinding TextBox to integer property in another object
提问by Dave
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)
我有一个我认为非常简单的数据绑定问题(我还是 WPF 的新手)。我有一堂课(针对这个问题进行了简化)
public class ConfigurationData
{
public int BaudRate { get; set; }
}
In MainWindow.Xaml.cs I have a private member variable:
在 MainWindow.Xaml.cs 我有一个私有成员变量:
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.
在我的 MainWindow gui 中,我想要一个显示 m_data.BaudRate 并允许双向绑定的 TextBox。用户应该能够在文本框中输入一个值,并且文本框应该显示我们由“DoStuff()”方法引起的新值。我已经看到了大量关于绑定到 MainWindow 上控件的另一个属性和绑定到数据集合的示例,但没有绑定到另一个对象的属性的示例。我会认为我的例子很简单,因为我绑定到一个整数而不是一个字符串,如果可能的话,我希望用户只能输入整数。
顺便说一句,我考虑过使用数字向上/向下,但决定反对它,因为似乎没有很多非商业数字向上/向下控件的支持/示例。另外,它可能是一个非常大的数字范围。
I think a pointer to one good example would get me on my way. Many thanks in advance, Dave
我认为一个很好的例子的指针会让我走上正轨。提前非常感谢,戴夫
回答by kmote
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:
为了支持双向绑定,您的初始ConfigurationData
类必须扩展以支持属性更改。否则更改DoStuff()
将不会反映在 UI 文本框中。这是一个典型的方法:
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:
我选择将文本框绑定放在 XAML 中(我还向 DoStuff 添加了一个按钮),如下所示:
<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:
棘手的部分是将这一切粘合在一起。为此,您需要定义您的 DataContext。我更喜欢在主窗口的构造函数中执行此操作。这是代码:
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;
}
}
回答by Dave
I'm sure there's a better way (please tell me!), but here's one way I cobbled together that works. It seems that there should be an easier way. For the property BaudRate use:
我确信有更好的方法(请告诉我!),但这是我拼凑起来的一种有效方法。似乎应该有更简单的方法。对于属性 BaudRate 使用:
public int BaudRate
{
get
{
return m_baudRate;
}
set
{
if (value != m_baudRate)
{
m_baudRate = value;
OnPropertyChanged("BaudRate");//OnPropertyChanged definition left out here, but it's pretty standard
}
}
}
For the XAML, I have no significant markup:
对于 XAML,我没有重要的标记:
<TextBox Height="23" Margin="137,70,21,0" Name="textBox1" VerticalAlignment="Top" />
Now this is the messy part... Create class for validation:
现在这是混乱的部分...创建用于验证的类:
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), have:
然后在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 markup failed. Better ways?
我在标记中做所有事情的所有尝试都失败了。更好的方法?
Dave
戴夫