2

Winforms .net 3.5 app. В моем приложении у меня есть общий класс, который выглядит так:ObservableCollection <T> в Winforms и возможных альтернативах

public class FilterItem { 
    public FilterItem() { } 
    public string FilterProperty { get; set; } 
    public bool FilterPropertyChecked { get; set; } 
    public ComparitiveOperator FilterOperator { get; set; } 
    public string FilterValue { get; set; } 
} 

и я использую его во всех своих диалоговых окнах, когда я хочу, чтобы реализовать некоторую функциональность фильтра. Поэтому я вызываю диалоговую форму с предварительно запутанным List<FilterItem>, переданным в конструкторе. Теперь, когда диалоговые нагрузки, он перебирает через каждый элемента списка и добавляет:

  1. Флажок
  2. выпадающий
  3. текстовое поле

к каждой строке в TableLayoutPanel. Флажок имеет свойство text от FilterProperty и его состояние «От проверено» от FilterPropertyChecked ... Combobox получает привязку с FilterOperator ... и текстовое поле получает текстовое значение от FilterValue.

Обратите внимание, что только Im только получает. То, что я хотел бы сделать, автоматически обновляет эти свойства, когда элементы управления, свойства которых они обязаны изменить. Я слышал о ObservableCollection<T>, но у меня нет доступа к нему в Winforms после добавления пространства имен System.Collections.ObjectModel.

Что было бы лучшим способом для этого. BindingList с INotifyPropertyChanged ?? Я не специалист с последним, и был бы очень признателен за некоторые указатели - если так я должен идти.

thank u!

EDIT:

Хорошо, позвольте мне опубликовать код, чтобы показать, что я думаю, что я должен делать :). Я знаю, что нужно реализовать INotifyPropertyChanged в моем классе FilterItem, так (только для части FilterValue, например):

public class FilterItem : INotifyPropertyChanged { 
    public FilterItem() { } 
    public string FilterProperty { get; set; } 
    public bool FilterPropertyChecked { get; set; } 
    public ComparitiveOperator FilterOperator { get; set; } 

    private string _FilterValue; 
    public string FilterValue { 
     get { return this._FilterValue; } 
     set { 
      if (this._FilterValue != value) { 
       this._FilterValue = value; 
       this.OnFilterValueChanged(); 
      } 
     } 
    } 

    #region INotifyPropertyChanged Members 
    protected void OnFilterValueChanged() { 
     var handler = this.PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs("FilterValue")); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 
} 

Теперь должны все собрались вместе в моем Form_Load (это только для Textbox части и Я опустил Checbox и ComboBox), как так:

private List<FilterItem> FilterList; // <-- this gets assigned to in the constructor 

private void dlgFilterData_Load(object sender, EventArgs e) { 
    foreach (FilterItem item in FilterList) { 
     txt = new TextBox(); 
     txt.DataBindings.Add("Text", item, "FilterValue", false, DataSourceUpdateMode.OnPropertyChanged); 
     txt.Dock = DockStyle.Fill; 
    } 
} 

DataBindings DataSource текстового поля является 'элемент' в FilterItem. Но теперь у меня, похоже, проблема с моей IDE для визуальной студии, поэтому не можете попробовать это, но когда я ее запустил. Теперь я хотел бы знать, будет ли эта настройка успешно помогать моему индивидуальному FilterItem s автоматически обновляться при изменении соответствующего свойства соответствующего управления?

+0

Должен ли я также использовать BindingList вместо обычного списка ? – Shalan

ответ

3

Класс ObservableCollection находится в сборке WindowsBase, поэтому вам нужно добавить WindowsBase в ваши ссылки на проект, чтобы «получить доступ» к нему.

Это, как говорится, я не думаю, что ObservableCollection даст вам все, что вы хотите. Ваш связанный элемент управления будет уведомлен при добавлении или удалении элементов, но автоматическое уведомление об изменении свойств отсутствует, что и похоже на то, что вам кажется.

Независимо от того, какую коллекцию вы используете, я думаю, что вы на правильном пути с INotifyPropertyChanged. Вот простой пример реализации INotifyPropertyChanged:

class Foo : INotifyPropertyChanged 
{ 
    #region Bar property 

    private string _bar; 
    public string Bar 
    { 
     get { return _bar; } 
     set 
     { 
      if (_bar != value) 
      { 
       _bar = value; 

       OnPropertyChanged("Bar"); 
      } 
     } 
    } 

    #endregion 

    protected void OnPropertyChanged(string name) 
    { 
     var handler = PropertyChanged; 

     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(name)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

В принципе, в любое время это свойство вашего объекта изменяется, огонь событие PropertyChanged, передавая имя свойства, которое изменилось.

Наконец, все это может быть спорным, поскольку вы сказали, что хотите изменить значение свойства объекта в ответ на изменение элемента управления, связанного с этим свойством. Обычная инфраструктура привязки данных Windows Forms может сделать это без помощи INotifyPropertyChanged или любого другого интерфейса. Вам нужно только реализовать INotifyPropertyChanged, если вам нужно уведомить связанный контроль изменений свойств объекта из других источников.

+0

Даниэль, благодарю вас за столько вашего ответа и кода! В ответ на вышесказанное, я не слишком уверен, что полностью понимаю ваше последнее предложение - не могли бы вы прояснить это для меня? Кроме того, я на правильном пути с привязкой к текстовым полям и с использованием BindingList вместо List? (Извините, мой VS IDE все еще на миг, но я подумал, что все его куча глупых надстроек, которые приводят к его сбою, теперь удаляют их, поэтому, надеюсь, получится шанс проверить все это). – Shalan

+1

Когда вы настраиваете двустороннюю привязку данных (нормальный случай) между объектом и элементом управления, инфраструктура будет пытаться обновить его в ответ на изменения в другом. Структура привязки данных уже знает, как определить, когда изменяется свойство встроенного элемента управления, поэтому оно может изменить свойство привязки объекта источника данных без какой-либо дополнительной помощи от вас. Если, с другой стороны, вы меняете значение свойства объекта источника данных в коде, структура не знает, как определить это (и обновить связанный элемент управления), если вы не правильно реализуете INotifyPropertyChanged. –

+1

Что касается использования BindingList vs List: учитывая, как вы создаете свою форму, это не имеет значения. Если бы вы привязывали вашу коллекцию объектов FilterItem непосредственно к чему-то вроде сетки или списка, BindingList сделал бы это так, чтобы добавление элемента в коллекцию добавило бы тот же элемент в сетку/список и наоборот. –