5

我有一个我认为是一个非常简单的数据绑定问题(我还是 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 上控件的另一个属性以及绑定到数据集合的示例,但没有绑定到另一个对象的属性的示例。我认为我的示例非常简单,但令人烦恼的是我绑定到一个整数而不是字符串,如果可能的话,我希望用户只能输入整数。
顺便说一句,我考虑使用数字上/下,但决定反对它,因为似乎没有很多非商业数字上/下控件的支持/示例。另外,它可能是一个非常大的数字范围。

我认为指向一个好例子的指针会让我上路。非常感谢,戴夫

4

3 回答 3

19

尽管这个问题很老,但它是一个很好的问题,很少有人简洁地回答。让我为访问此页面的其他人提供一个简化的解决方案。

为了支持双向绑定,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;
    }
}
于 2011-08-10T21:53:59.627 回答
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);

我在标记中做所有事情的所有尝试都失败了。更好的方法?

戴夫

于 2010-10-08T14:44:00.077 回答
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”的值,文本框得到通知并自动更新,而无需定义类。

于 2020-06-09T06:18:22.073 回答