RaisePropertyChanged 不更新 UI

发布于 2024-12-02 04:02:02 字数 7383 浏览 1 评论 0原文

当我的 ViewModel 更改时,我无法让 UI 更新两个列表框以正确更新。

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

Movie是一个带有标题的对象,以及各种MovieDetails。有些 MovieDetail 与其他的不同,因为它们详细,这是一种美化的方式来表达它们更重要。 我使用两个 ListBoxes 将这些 MovieDetails 分成堆叠 ListBoxes,一个用于“Detailed”,一个用于“NotDetailed” ' 如果电影没有“详细”属性,则相应的列表将通过 BooleanToVisibilityConverter 隐藏(反之亦然)

当我导航到该页面时,我将 Movie 设置为页面对应,并且应该 RaisePropertyChanged 来提醒 AllMoviesDetail ObservableCollection 它应该重新获取Movies.MovieDetailFetchedList。 从那里,AllMoviesDetail 将提醒两个 ObservableCollections(Detailed、NotDetailed) 它们应该重新获取

事实上,NotDetailedMovieDetailsDetailedMovieDetails 上的 RaisePropertyChanged 似乎也没有执行任何操作。 (以及相应的 HasNotDetailedMovieDetails, Has...

但是,有效的是,如果我向列表中添加更多项目,CollectionChanged 事件似乎会触发并重新激活列表。我还可以通过在代码中首先实例化 ObservableCollections 来实现此目的 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; }
    }
}

I'm having trouble getting my UI to update Two Listboxes' to update properly when my ViewModel changes.

First, the basic logic behind the page:

Movie is an object with a title, and a variety of MovieDetails. Some MovieDetail are different than others, as they are detailed which is a glorified way of saying they're more Important.
I use two ListBoxes to separate these MovieDetails into stacked ListBoxes, one for 'Detailed' and one for 'NotDetailed'
If a movie has no 'Detailed' attributes, the corresponding list is Hidden via a BooleanToVisibilityConverter (and vice-versa)

When I navigate to the page, I set the Movie the page corresponds to, and it should RaisePropertyChanged to alert the AllMoviesDetail ObservableCollection that it should re-get Movies.MovieDetailFetchedList.
From there, AllMoviesDetail would alert the two ObservableCollections (Detailed, NotDetailed) they should be re-get.

In fact, RaisePropertyChanged on NotDetailedMovieDetails or DetailedMovieDetails does not seem to do anything either. (And the corresponding HasNotDetailedMovieDetails, Has...)

What does work, however, is if I add more items into the list, the CollectionChanged event seems to fire and reactivate the list. I have also been able to do this by instantiating the ObservableCollections in code first 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; }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

醉生梦死 2024-12-09 04:02:02

所有属性 getter(AllMoviesDetail 除外)都有两个 return 语句。由于仅执行第一个,因此不会分配值,并且不会触发 PropertyChanged 事件。

All of your property getters (except AllMoviesDetail) have two return statements. Since only the first will be executed, the values are not being assigned and the PropertyChanged events are not being twiggered.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文