0

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.

Gaurav
  • 3
  • 2

1 Answers1

0

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.

Community
  • 1
  • 1
devdigital
  • 34,151
  • 9
  • 98
  • 120
  • Thanks for your response... but unfortunately this doesn't help. The OnPropertyChanged() is called in the UI thread. That's how the list gets displayed at the first place. The problem is switching between collections. On switching collections the list item go away one by one. – Gaurav Jul 28 '11 at 02:42
  • are you able to upload the source that replicates the problem somewhere? – devdigital Jul 28 '11 at 08:27
  • Hi There, thanks for the follow up. I tried to create a sample project to replicate the problem. But the same thing works in that project. I might be missing something in my actual project. BTW here's the sample for your reference: http://db.tt/pQdrSzO – Gaurav Aug 10 '11 at 07:20