INotifyPropertyChanged'双'绑定

时间:2011-07-24 23:01:06

标签: c# wpf xaml windows-phone-7 mvvm-light

我正在尝试将一些XAML代码绑定到我的ViewModel中的属性。

<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 个答案:

答案 0 :(得分:3)

直接暴露ViewModel中的对象并直接通过它进行绑定(以便不仅仅复制一次现在发生的值)或者订阅PropertyChanged事件并将HasMovies设置为每个新值它在源对象中发生变化的时间。

e.g。

CP.Connection.PropertyChanged += (s,e) =>
    {
        if (e.PropertyName = "HasMovies") this.HasMovies = CP.Connection.HasMovies;
    };

答案 1 :(得分:1)

首先,更改集合的内容时,调用集合类型的setter(例如MovieList属性)(即添加/删除项目。)

这意味着MovieList属性的所有setter代码都是毫无意义的。

其次,这是非常愚蠢的代码。一个更好的解决方案是使用NotifyPropertyWeaver。然后你的代码看起来像这样,在viewmodel中:

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

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

或者,当你第一次初始化MovieList属性时,你必须为CollectionChanged事件添加一个监听器(没有理由拥有支持属性,真的没有理由!),然后调用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));
        }
    }
}