INotifyPropertyChanged 'Двойная' привязка - PullRequest
1 голос
/ 25 июля 2011

Я пытаюсь привязать некоторый код XAML к свойству в моей модели представления.

<Grid Visibility="{Binding HasMovies, Converter={StaticResources VisibilityConverter}}">
...
</Grid>

Моя ViewModel настроена так:

private bool _hasMovies;
        public bool HasMovies
        {
            get { return _hasMovies; }
            set { _hasMovies = value; RaisePropertyChanged("HasMovies"); }
        }

В конструкторе ViewModel я установил ссылку HasMovies:

MovieListViewModel()
{
   HasMovies = CP.Connection.HasMovies;
}

в CP:

public bool HasMovies
        {
            get { return MovieList != null && MovieList.Count > 0; }
        }

private ObservableCollection<Movie> _movies;
        public ObservableCollection<Movie> MovieList
        {
            get { return _movies; }
            set
            {
                _movies = value;
                RaisePropertyChanged("MovieList");
                RaisePropertyChanged("HasMovies");
                _movies.CollectionChanged += MovieListChanged;
            }
        }

        private void MovieListChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            RaisePropertyChanged("HasMovies");
        }

Что я делаю не так? Как мне изменить эту привязку, чтобы она отражала текущее состояние CP.Connection.HasMovies?

Ответы [ 2 ]

3 голосов
/ 25 июля 2011

Либо напрямую выставьте объект во ViewModel и связывайте напрямую через него (чтобы значение не просто копировалось один раз, как это происходит сейчас), либо подпишитесь на событие PropertyChanged и установите HasMovies на новое значение каждый раз, когда оно изменения в вашем исходном объекте.

, например

CP.Connection.PropertyChanged += (s,e) =>
    {
        if (e.PropertyName = "HasMovies") this.HasMovies = CP.Connection.HasMovies;
    };
1 голос
/ 25 июля 2011

Прежде всего, метод установки для типа коллекции, например вашего свойства MovieList, не вызывается при изменении содержимого коллекции (т. Е. Добавление / удаление элементов).

Это означает, что весь ваш установочный код для свойства MovieList не имеет смысла.

Во-вторых, это очень глупый код.Гораздо лучшим решением является использование NotifyPropertyWeaver .Тогда ваш код будет выглядеть следующим образом в viewmodel:

[DependsOn("MovieList")]
public bool HasMovies
{
    get { return MovieList != null && MovieList.Count > 0; }
}

public ObservableCollection<Movie> MovieList
{
    get;
    private set;
}

В качестве альтернативы вам придется добавить прослушиватель для события CollectionChanged, когда вы инициализируете свойство MovieList в первый раз (нет причин иметь свойство backingдействительно нет причин!), а затем вызовите RaisePropertyChanged ("HasMovies") в обработчике событий.

Пример:

public class CP : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public CP()
    {
        MovieList = new ObservableCollection<Movie>();
        MovieList.CollectionChanged += MovieListChanged;
    }

    public bool HasMovies
    {
        get { return MovieList != null && MovieList.Count > 0; }
    }

    public ObservableCollection<Movie> MovieList
    {
        get;
        private set;
    }

    private void MovieListChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        RaisePropertyChanged("HasMovies");
    }

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