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 VerticalA开发者_JS百科lignment="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.
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.
精彩评论