Отсутствует событие PropertyChanged, когда у элементов BindingList изменились свойства - PullRequest
0 голосов
/ 30 сентября 2011

У меня есть класс ViewModel со свойством MyList типа BindingList<Foo>.

ViewModel реализует INotifyPropertyChanged.

Foo имеет свойство FooProp.

Foo реализует INotifyPropertyChanged

ViewModel обладает этим свойством:

public bool IsButtonEnabled
  {
    get
    {
      return MyList.Any(x=> x.FooProp!=null);
   }
}

У меня есть вид с кнопкой. Свойство Enabled кнопки привязано к IsButtonEnabled.

Но кнопка не активируется, когда для элемента MyList установлено FooProp. Я заметил, что ViewModel не запускает здесь событие PropertyChanged. Почему бы и нет? И как мне сделать так, чтобы модель представления заметила, что ее свойство IsButtonEnabled действительно изменилось?

Ответы [ 2 ]

0 голосов
/ 30 сентября 2011

ViewModel не будет запускать здесь любую PropertyChanged, потому что свойства ViewModel не изменяются.Фактическое свойство, которое было изменено FooProp, которое является свойством класса Foo, а не ViewModel.

Чтобы включить / отключить кнопку на основе функциональности IsButtonEnabled, вам необходимо будет отслеживать все элементыMyList и посмотреть, если какие-либо изменения сделаны.Итак, должно работать следующее:

public class Foo : INotifyPropertyChanged
{
    void OnPropertyChanged(string propertyName) { /* ... */ }
    public object FooProp 
    { 
        get { return _obj; }
        set 
        {
            _obj = value;
            OnPropertyChanged("FooProp");
        }
    }
}

public class ViewModel : INotifyPropertyChanged
{
    void OnPropertyChanged(string propertyName) { /* ... */ }

    private List<Foo> _myList;
    public List<Foo> MyList 
    { 
        get { return _myList; }
        set 
        {
            _myList = value;
            foreach(var item in _myList) 
            {
                HandleItem(item);
            }
        }
    }

    void AddItem(Foo item) 
    {
        MyList.Add(item);
        HandleItem(item);
    }
    void HandleItem(Foo item) 
    {
        item.PropertyChanged += (s, e) =>
        {
            if(e.PropertyName == "FooProp")
        };
    }
    void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName == "FooProp") OnPropertyChanged("IsButtonEnabled");
    }
    public bool IsButtonEnabled
    {
        get
        {
          return MyList.Any(x=> x.FooProp!=null);
        }
    }
}

Обратите внимание, что в этом случае вам нужно использовать ViewModel.AddItem () для добавления элемента в MyList (вы можете использовать MyList.Add (), но этотогда не будут генерироваться правильные уведомления).

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

0 голосов
/ 30 сентября 2011

РЕДАКТИРОВАНИЕ: Не заметил, что это геттер, а не сеттер.Дело в том же.Простая реализация интерфейса INotifyPropertyChanged не добавляет автоматически все, что вам нужно.Вам необходимо создать метод (ниже), который запускает событие.Затем вам нужно вызвать этот метод в SETTER всех ваших свойств.

Разве вы не должны запускать событие PropertyChanged самостоятельно?

public bool IsButtonEnabled
{
    get
    {
        return MyList.Any(x=> x.FooProp!=null);

        // assuming you named the method this
        OnPropertyChanged("IsButtonEnabled");
    }
}

Интерфейс INotifyPropertyChanged создает только событиедля тебя.Вам нужно запустить событие из ViewModel самостоятельно.

Если вы еще не создали метод, этот обычно работает.Этот метод вызывается явным образом при изменении свойства ViewModel.

private void OnPropertyChanged(string propertyName)
{
    var handler = PropertyChanged;
    if (handler != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
...