我认为这是一个非常简单的数据绑定问题(我还是WPF的新手)。 我有一个班级(这个问题简化了)
public class ConfigurationData
{
public int BaudRate { get; set; }
}
在MainWindow.Xaml.cs中我有一个私有成员变量:
private ConfigurationData m_data;
和方法
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
}
在我的MainWindow gui中,我想要一个显示m_data.BaudRate的TextBox,并允许双向绑定。用户应该能够在文本框中输入值,文本框应该显示我们由“DoStuff()”方法引起的新值。我已经看到大量关于绑定到MainWindow上的控件的另一个属性的示例,以及绑定到datacollection,但没有绑定到另一个对象的属性的示例。我认为我的例子就像它得到的一样简单,令人烦恼的是我正在绑定一个整数,而不是一个字符串,如果可能的话,我希望用户只能输入整数。 /> BTW我考虑使用数字上/下,但决定反对它,因为似乎没有很多支持/非商业数字上/下控制的例子。此外,它可能是一个非常大的数字范围。
我认为指向一个好例子的指针会让我走上正轨。 提前谢谢了, 戴夫
答案 0 :(得分:17)
虽然这个问题很老,但这个问题很好,而且很少能够简洁地回答。让我为访问此页面的其他人提供简化的解决方案。
为了支持双向绑定,必须扩展初始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));
}
}
}
我选择将文本框绑定放在XAML中(我还添加了一个DoStuff按钮),如下所示:
<Canvas>
<TextBox Width="96" Name="textBox1" Text="{Binding BaudRate}" />
<Button Width="96" Canvas.Top="25" Content="ChangeNumber" Click="DoStuff"/>
</Canvas>
棘手的部分是将这一切粘在一起。为此,您需要定义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;
}
}
答案 1 :(得分:0)
我确信有更好的方法(请告诉我!),但这是我拼凑起来的一种方式。似乎应该有一种更简单的方法。 对于属性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
}
}
}
对于XAML,我没有重要的标记:
<TextBox Height="23" Margin="137,70,21,0" Name="textBox1" VerticalAlignment="Top" />
现在这是一个混乱的部分......创建验证类:
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);
}
}
}
然后在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);
我在标记中做所有事情的所有尝试都失败了。更好的方式?
戴夫
答案 2 :(得分:0)
是否有一种更简单的方法而无需定义这样的公共类和它自己的方法? 我之所以问是因为,当我将文本框和滑条一起使用时,实际上我可以将滑条的名称与文本框绑定为元素名称。
我的代码如下:
<TextBox Text="{Binding ElementName=slValue, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
<Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slValue" />
因此,必须已经存在某些东西,例如从滑动条中使用的东西。
我需要做的就是简单地从源代码中分配“ slValue”的值,文本框会收到通知并自动更新,而无需定义类。
答案 3 :(得分:-2)