2010-10-07 3 views
4

У меня есть то, что я считаю очень простым вопросом привязки данных (я все еще новичок в WPF). У меня есть класс (упрощенный для этого вопроса)WPF привязка данных TextBox к целочисленному свойству в другом объекте

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

Я думаю, что указатель на один хороший пример заставит меня идти в мою сторону. Большое спасибо заранее, Дэйв

+1

Я должен был сказать, что, по-моему, указатель на один хороший пример поставил бы меня на моем пути. – Dave

+0

Это не работает (синтаксическая ошибка) Я видел, что можно настроить «ресурс» в Xaml. Казалось бы, это слишком сложно для меня. Разве я не могу сделать это как-то? Это единственный раз, когда я буду привязываться к m_data. Кроме того: возможно ли форматировать код или использовать ключ возврата в комментариях :)? – Dave

+0

Просто хотел заметить, что числовой элемент управления сверху вниз (или счетчика) также помогает предотвратить нечистовой ввод клавиатуры и минимальные/максимальные проверки, а не только фактическое вращение чисел. Я думаю, что есть один в Bag of Tricks, который делает работу прилично (вам нужно только правильно ее подстроить). –

ответ

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); 

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

Dave

16

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

Для поддержки двусторонней привязки ваш начальный класс 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; 
    } 
}