Kamil
Kamil

Reputation: 13941

How to disable ListView selection change when item has changes in MVVM/MVW?

I have simple viewmodel:

private List<Item> itemsList;
public List<Item> ItemsList
{
    get { return itemsList; }
    set
    {
        itemsList= value;
        NotifyPropertyChanged();
    }
}

private Item selectedItem;
public Item SelectedItem
{
    get { return selectedItem; }
    set
    {
        selectedItem = value;
        NotifyPropertyChanged();
    }
}

// I call this method from button handler 
// window code behind: vm.SaveChanges()
// instead of RelayCommand because I'm lazy (I don't need strict MVVM)
public void SaveChanges() 
{
    context.SaveChanges();
}

Im my view I have a ListView:

<ListView 
    ItemsSource="{Binding ItemsList}" 
    SelectedItem="{Binding SelectedItem}" 
/>

and few controls with Item properties:

<TextBox Text="{Binding SelectedItem.Name}"/>
<TextBox Text="{Binding SelectedItem.Phone}"/>

When I select an Item on a ListView - SelectedItem field values appear in TextBoxes, I can edit them and save them. Everything works fine, but I don't want to allow user to change selected item before he saves changes, because user will not see what was changed in another item(s).

Now I want to disable selection change on ListView, when item has unsaved changes.

I was experimenting with ViewModel property like this:

public bool NoUnsavedChanges
{
    get { return !context.ChangeTracker.HasChanges(); }
    private set;
}

and binding it to IsEnabled property of ListView, but of course it does not work because there is no NotifyPropertyChanged() for this property.

My question is: how can I disable ListView selection change (or disable it totally) when selected item (or if there are unsaved changes in the entire context)?

Upvotes: 0

Views: 1172

Answers (1)

mm8
mm8

Reputation: 169420

...and binding it to IsEnabled property of ListView, but of course it does not work because there is no NotifyPropertyChanged() for this property.

Raise a PropertyChanged event then. Your view model should implement the INotifyPropertyChanged event and so should your Item class. If it doesn't you should replace it with a wrapper class that does. You could then raise the PropertyChanged event for the NoUnsavedChanges property of the view model whenever the state of the SelectedItem changes, e.g.:

private List<Item> itemsList;
public List<Item> ItemsList
{
    get { return itemsList; }
    set
    {
        itemsList = value;
        NotifyPropertyChanged();
    }
}

private Item selectedItem;
public Item SelectedItem
{
    get { return selectedItem; }
    set
    {
        if (selectedItem != null)
            selectedIten.PropertyChanged -= OnItemPropertyChanged;

        selectedItem = value;
        NotifyPropertyChanged();

        if (selectedItem != null)
            selectedIten.PropertyChanged += OnItemPropertyChanged;
    }
}

private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    NotifyPropertyChanged("NoUnsavedChanges");
}

public bool NoUnsavedChanges
{
    get { return !context.ChangeTracker.HasChanges(); }
}

public void SaveChanges()
{
    context.SaveChanges();
    NotifyPropertyChanged("NoUnsavedChanges");
}

Upvotes: 1

Related Questions