2011-08-29 129 views
2

我无法让我的用户界面更新两个Listboxes,以在我的ViewModel更改时正确更新。RaisePropertyChanged不更新UI

首先,页面背后的基本逻辑:

电影是具有标题的对象,以及各种MovieDetails。有些MovieDetail是比别人不同,因为它们是详细这是说他们是更重要的一个华而不实的方式。 我使用两个ListBoxes分离这些MovieDetails堆叠ListBoxes,一个用于“详细”,一个用于“NotDetailed” 如果电影没有“详细”属性,相应列表经由BooleanToVisibilityConverter(反之亦然隐藏)

当我浏览网页,我设置了Movie页面对应,应该RaisePropertyChanged提醒AllMoviesDetailObservableCollection,它应该重新得到Movies.MovieDetailFetchedList。 从那里,AllMoviesDetail将提醒两个ObservableCollections (Detailed, NotDetailed)他们应该重新get

实际上,NotDetailedMovieDetailsDetailedMovieDetails上的RaisePropertyChanged似乎也没有做任何事情。 (和相应的HasNotDetailedMovieDetails, Has...

然而,如果我向列表中添加更多项目,CollectionChanged事件似乎会触发并重新激活列表,那么工作是什么。我还通过在代码第一var temp = DetailedMoviesDetail;

public class MoviesDetailViewModel : ViewModelBase 
{ 
    #region Property Names 

    public const string MoviePropertyString = "Movie"; 
    public const string AllMoviesDetailPropertyString = "AllMoviesDetail"; 
    public const string DetailedMoviesDetailPropertyString = "DetailedMoviesDetail"; 
    public const string NotDetailedMoviesDetailPropertyString = "NotDetailedMoviesDetail"; 
    public const string HasNotDetailedMoviesDetailPropertyString = "HasNotDetailedMoviesDetail"; 
    public const string HasDetailedMoviesDetailPropertyString = "HasDetailedMoviesDetail"; 
    public const string NotDetailedHeaderPropertyString = "NotDetailedHeader"; 

    #endregion 


    public MoviesDetailViewModel() 
    { 
     if (IsInDesignMode) 
     { 
      Movie = DesignDataStore.MovieList[0]; 
      Movie.Category = Category.DDA; 
     } 
    } 

    private Movie _Movie; 

    /// <summary> 
    /// The Movie for which to browse MoviesDetail. It is expected when setting this property, that MoviesDetail for it have been downloaded previously. 
    /// </summary> 
    /// <remarks>The 'Master' property for this ViewModel. All properties are Dependent on this and the underlying property MoviesDetailList</remarks> 
    /// <seealso cref="MovieDetailFetchedList"/> 
    public Movie Movie 
    { 
     get { return _Movie; } 
     set 
     { 
      if (_Movie != value) 
      { 
       if (_Movie != null) 
        _Movie.MovieDetailFetchedList.CollectionChanged -= MoviesDetailListChanged; 


       _Movie = value; 

       RaisePropertyChanged(MoviePropertyString); 
       RaisePropertyChanged(StatementPeriodAvailablePropertyString); 
       RaisePropertyChanged(NotDetailedMoviesDetailPropertyString); 
       Movie.MovieDetailFetchedList.CollectionChanged += MoviesDetailListChanged; 

       RaisePropertyChanged(AllMoviesDetailPropertyString); 

       RaisePropertyChanged(DetailedMoviesDetailPropertyString); 

       RaisePropertyChanged(NotDetailedHeaderPropertyString); 
      } 
     } 
    } 

    private void MoviesDetailListChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      foreach (var item in e.NewItems) 
      { 
       if (((MovieDetail) item).IsDetailed()) 
        DetailedMoviesDetail.Add(item as MovieDetail); 
       else 
        NotDetailedMoviesDetail.Add(item as MovieDetail); 
      } 
     } 
     else 
     { 
      RaisePropertyChanged(AllMoviesDetailPropertyString); 
      RaisePropertyChanged(DetailedMoviesDetailPropertyString); 
      RaisePropertyChanged(NotDetailedMoviesDetailPropertyString); 
     } 
    } 




    #endregion 

    private MovieDetailFetchedList _allMoviesDetail; 
    public MovieDetailFetchedList AllMoviesDetail 
    { 
     get 
     { 
      if (Movie == null) 
       return new MovieDetailFetchedList(); 

      return _allMoviesDetail ?? (AllMoviesDetail = Movie.MovieDetailFetchedList); 
     } 
     set 
     { 
      if (_allMoviesDetail != value) 
      { 
       if (_allMoviesDetail != null) 
        _allMoviesDetail.CollectionChanged -= MoviesDetailListChanged; 
       _allMoviesDetail = value; 
       _allMoviesDetail.CollectionChanged += MoviesDetailListChanged; 

       RaisePropertyChanged(AllMoviesDetailPropertyString); 
       //force update 
       DetailedMoviesDetail = NotDetailedMoviesDetail = null; 
       RaisePropertyChanged(DetailedMoviesDetailPropertyString); 
       RaisePropertyChanged(HasDetailedMoviesDetailPropertyString); 
       RaisePropertyChanged(NotDetailedMoviesDetailPropertyString); 
       RaisePropertyChanged(HasNotDetailedMoviesDetailPropertyString); 
      } 

     } 
    } 

    public bool HasNotDetailedMoviesDetail { get { return NotDetailedMoviesDetail != null && NotDetailedMoviesDetail.Count > 0; } } 



    private ObservableCollection<MovieDetail> _notDetailedMoviesDetail; 
    public ObservableCollection<MovieDetail> NotDetailedMoviesDetail 
    { 
     get 
     { 
      if (Movie == null) return new ObservableCollection<MovieDetail>(); 

      return AllMoviesDetail; 
       return _notDetailedMoviesDetail ?? //make sure RaisePropertyChanged happens by using property setter 
       (NotDetailedMoviesDetail = AllMoviesDetail.Where(mem => !mem.IsDetailed()).ToObservableCollection()); 
     } 
     set 
     { 
      _notDetailedMoviesDetail = value; 
      RaisePropertyChanged(NotDetailedMoviesDetailPropertyString); 
      RaisePropertyChanged(HasNotDetailedMoviesDetailPropertyString); 
     } 
    } 

    public bool HasDetailedMoviesDetail 
    { get { return DetailedMoviesDetail != null && DetailedMoviesDetail.Count > 0; } } 

    private ObservableCollection<MovieDetail> _DetailedMoviesDetail; 
    public ObservableCollection<MovieDetail> DetailedMoviesDetail 
    { 
     get 
     { 
      if (Movie == null) return new ObservableCollection<MovieDetail>(); 

      return AllMoviesDetail; 
      return _DetailedMoviesDetail ?? //make sure RaisePropertyChanged happens by using property setter 
      (DetailedMoviesDetail = AllMoviesDetail.Where(mem => mem.IsDetailed()).ToObservableCollection()); 
     } 
     set 
     { 
      _DetailedMoviesDetail = value; 
      RaisePropertyChanged(DetailedMoviesDetailPropertyString); 
      RaisePropertyChanged(HasDetailedMoviesDetailPropertyString); 
     } 
    } 


    private string _DetailedHeader; 
    public string DetailedHeader 
    { 
     get { return _DetailedHeader ?? (_DetailedHeader = AppResources.in_available); } 
     set { _DetailedHeader = value; } 
    } 

    public string NotDetailedHeader 
    { 
     get { return (Movie != null && Movie.Category == Category.DRAMA) ? AppResources.Movie_MoviesDetail : AppResources.not_in_available; } 
    } 
} 
+3

感谢您的详细问题。不过,如果你能提供一个更小的代码样本来重现你的问题,它会更有帮助。在很多情况下,编写一个最小示例的过程将为您提供自己解决问题所需的洞察力。 – Dathan

+0

还包括显示实现INotifyPropertyChanged的类的代码。 –

回答

4

全部财产干将(除AllMoviesDetail)实例化ObservableCollections已经 return语句之所以能够做到这一点。由于只有第一个被执行,所以这些值没有被赋值,并且PropertyChanged事件没有被分割。

+0

是否有2个语句可以留给不同的代码执行?我应该如何处理这个事情,因为在它们实际工作之前对象是通过(通过'NavigationContext绑定)访问的? –

+1

@willmel - 返回语句将在该点结束执行。通常的模式不是在“get”中计算,而是在中心点进行计算,然后提高适当的属性更改事件。 –

+0

感谢您的回应。我明白,getter变成setter并没有什么意义 - 但是如何重写它以便'Binding'在“Movie”对象被设置之前正常工作?即如果我正在根据OnNavigatedTo中的QueryString设置我的电影对象,则UI已经被处理并且绑定已经发生(对于无效的值,因为尚未设置电影)。谢谢..你的回应非常感谢。 –