【问题标题】:Binding ListBox not updating on swapping ObservableCollection even on INotifyPropertyChanged即使在 INotifyPropertyChanged 上,绑定 ListBox 也不会在交换 ObservableCollection 时更新
【发布时间】:2011-10-13 22:38:31
【问题描述】:

我是 WPF 的新手。我已经实现了一个 M-V-VM 解决方案,并为所有需要反映在 UI 上的属性实现了 INotifyPropertyChanged。到目前为止,一切似乎都运行良好,除了一个绑定到只读属性的列表框,该属性返回一个可观察的集合。

ViewModelBase 实现了 INotifyPropertyChanged 接口:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    .....
    INotifyPropertyChanged Implementation
    .....

    OnPropertyChanged(...)
    {
        .....
    }  
}

MainViewModel 类继承 ViewModelBase 并保存 UI(视图)的数据。 BackgroundWorker 创建 UserViewModel 对象。对象被添加到 ObservableCollection。 ListBox 显示 UserViewModel ObservableCollection。

在创建 User 对象时,它被添加到 ObservableCollection 中,并调用 OnPropertyChanged 来通知 UI 元素刷新。这工作正常。

当用户选择仅查看收藏夹时,从视图中删除一个用户项目。选中和取消选中复选框具有相同的效果......也就是说,从列表视图中删除了一个用户项目。而预期的行为是在可观察集合之间切换。

public class MainViewModel : ViewModelBase
{    
    private ObservableCollection<UserViewModel> mUsers = new ObservableCollection<UserViewModel>();
    private ObservableCollection<UserViewModel> mFavoriteUsers = new ObservableCollection<UserViewModel>();
    UserViewModel mSelectedUser;
    private bool mbShowFavorite;

    public bool ShowFavorite
    {
        get { return this.mbShowFavorite; }
        set
        {
            this.mbShowFavorite = value;
            OnPropertyChanged("ShowFavorite");
            OnPropertyChanged("Users");
        }
    }

    public UserViewModel SelectedUser
    {
        get { return this.mSelectedUser; }
        set
        {
            this.mSelectedUser = value;
            OnPropertyChanged("SelectedUser");
        }
    }

    public ObservableCollection<UserViewModel> Users
    {
        get 
        {
            if (this.mbShowFavorite)
                return this.mFavoriteUsers;
            else
                return this.mUsers;
        }
    }

    .....
    Other Class Members
    .....

    void BackgroundCreateUserModelsCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Add the User View Model
        this.mUsers.Add((UserViewModel)e.Result);

        if (((UserViewModel)e.Result).IsFavorite)
        {
            this.mFavoriteUsers.Add((UserViewModel)e.Result);
        }

        // Users changed: Notify Property Changes
        OnPropertyChanged("Users");
    }
}

这是与上述代码相关的 XAML 视图。

<CheckBox VerticalAlignment="Center" Content="Show Favorites"
    IsChecked="{Binding Path=ShowFavorite, Mode=TwoWay}" />

<ListBox Name="listboxUsers"
    ItemsSource="{Binding Path=Users}" 
    SelectedItem="{Binding SelectedUser, Mode=TwoWay}">            
    <ListBox.ItemTemplate>
        <DataTemplate>
            <views:UserView></views:UserView>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>    

我的问题是,我该如何让它发挥作用。我需要根据是否选中“收藏夹”复选框来交换视图。

【问题讨论】:

    标签: mvvm binding observablecollection inotifypropertychanged swap


    【解决方案1】:

    此问题可能与未编组到 UI 线程的集合更改有关。请参阅Making sure OnPropertyChanged() is called on UI thread in MVVM WPF app 了解更多信息。

    【讨论】:

    • 感谢您的回复...但不幸的是,这无济于事。在 UI 线程中调用 OnPropertyChanged()。这就是列表首先显示的方式。问题是在集合之间切换。在切换集合时,列表项会一一消失。
    • 您能否上传在某处复制问题的源代码?
    • 您好,感谢您的跟进。我试图创建一个示例项目来复制问题。但同样的事情也适用于那个项目。我可能在我的实际项目中遗漏了一些东西。顺便说一句,这是供您参考的示例:db.tt/pQdrSzO
    猜你喜欢
    • 2012-02-29
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    相关资源
    最近更新 更多