即使在 INotifyPropertyChanged 上,绑定 ListBox 也不会在交换 ObservableCollection 时更新

发布于 2024-11-26 06:08:27 字数 2851 浏览 6 评论 0原文

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

ViewModelBase 实现 INotifyPropertyChanged 接口:

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

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

MainViewModel 类继承 ViewModelBase 并保存 UI(View)的数据。 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>    

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

I'm a newbie in WPF. I've implemented an M-V-VM solution and implemented INotifyPropertyChanged for all properties that need to reflect on the UI. Everything seems to be working ok so far, except for a listbox bound to a read-only property which returns an observable collection.

ViewModelBase implements the INotifyPropertyChanged interface:

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

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

MainViewModel class inherits ViewModelBase and holds the data for the UI (View). A BackgroundWorker creates the UserViewModel objects. The objects are added to the ObservableCollection. The ListBox displays the UserViewModel ObservableCollection.

As and when the User object is created it is added to the ObservableCollection and OnPropertyChanged is called to notify the UI elements to refresh. This works ok.

When user selects to view Favorites only, one User item from view is removed. Checking & Unchecking the checkbox has the same effect... that is, an user item is removed from the list view. While the expected behavior is to switch between the observable collections.

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");
    }
}

Here is the XAML view relevant to the above code.

<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>    

My question is, how do I get this to work. I need to swap the views based on whether the Favorite checkbox is checked or not.

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

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

发布评论

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

评论(1

葵雨 2024-12-03 06:08:27

该问题可能与集合更改未编组到 UI 线程有关。请参阅确保调用 OnPropertyChanged()有关详细信息,请参阅 MVVM WPF 应用程序中的 UI 线程

The problem may be related to collection changes not being marshalled to the UI thread. See Making sure OnPropertyChanged() is called on UI thread in MVVM WPF app for more info.

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