WPF Databinding привязка TextBox к целочисленному свойству в другом объекте - PullRequest
4 голосов
/ 08 октября 2010

У меня есть очень простой вопрос, связанный с данными (я все еще новичок в 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 мне бы хотелось иметь TextBox, который отображает m_data.BaudRate AND и допускает двухстороннее связывание. Пользователь должен иметь возможность ввести значение в текстовое поле, а в текстовом поле должны отображаться новые значения, вызванные методом «DoStuff ()». Я видел множество примеров привязки к другому свойству элемента управления в MainWindow и привязки к коллекции данных, но примеров привязки к свойству другого объекта не было. Я думаю, что мой пример настолько прост, насколько это возможно, с неприятным раздражением, связанным с целым числом, а не со строкой, и, если возможно, я бы хотел, чтобы пользователь мог вводить только целые числа.
Кстати, я подумал об использовании числового вверх / вниз, но решил не делать этого, так как, похоже, не было большой поддержки / примеров некоммерческих числовых элементов управления вверх / вниз. Кроме того, это может быть ужасно большой диапазон чисел, через которые можно вращаться.

Я думаю, что указание на один хороший пример поможет мне в моем пути. Спасибо заранее, Dave

Ответы [ 2 ]

17 голосов
/ 11 августа 2011

Хотя этот вопрос старый, он хороший, и на него редко дается краткий ответ. Позвольте мне предложить упрощенное решение для тех, кто заходит на эту страницу.

Чтобы поддерживать двустороннюю привязку, ваш исходный класс ConfigurationData должен быть расширен для поддержки изменений свойств. В противном случае изменения в DoStuff() не будут отражены в текстовом поле интерфейса пользователя. Вот типичный способ сделать это:

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;
    }
}
0 голосов
/ 08 октября 2010

Я уверен, что есть лучший способ (пожалуйста, скажите мне!), Но вот один способ, которым я соединился, который работает.Кажется, что должен быть более легкий путь.Для свойства 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);

Все мои попытки сделать все в разметке потерпели неудачу.Лучшие пути?

Дэйв

...