2

I'm trying to remove an item from a ListBox. The command is properly fired and the item is correctly removed from the database but the list is not refreshed.

Here is the ViewModel. I'm using MVVM Light 4.1

public class ViewAllViewModel : ViewModelBase
{
    public ViewAllViewModel()
    {
        NavigateToAddNew = new RelayCommand(() => NavigationController<Views>.Current.NavigateTo(Views.AddNew));
        Remove = new RelayCommand<int>(DeleteMeasure);

        using (var repository = App.ServiceLocator.Get<IRepository>())
        {
            Measures = new ObservableCollection<Measure>(repository.Measures);
        }
    }

    private void DeleteMeasure(int measureId)
    {
        Measure measure;

        using (IRepository repository = App.ServiceLocator.Get<IRepository>())
        {
            measure = repository.Measures.Single(m => m.Id == measureId);
            repository.Measures.Delete(measure);
            repository.SaveChanges();
        }

        measure = Measures.Single(m => m.Id == measureId);
        if (Measures.Remove(measure))
        {
            RaisePropertyChanged(() => Measures);
        }
    }

    public RelayCommand NavigateToAddNew { get; set; }
    public RelayCommand<int> Remove { get; set; }

    private ObservableCollection<Measure> _measures;
    public ObservableCollection<Measure> Measures
    {
        get { return _measures; }
        set { Set(() => Measures, ref _measures, value); }
    }
}

Thanks for the help.

PS: I know there are similar questions but none of the accepted answers worked for me :(

EDIT 1 This is the code I use in the XAML page to bind the ListBox to the list of items:

<ListBox Grid.Row="1" DataContext="{Binding Path=Measures}" ItemsSource="{Binding}" />

here is the binding of the ViewModel to the main container

<Grid DataContext="{Binding Source={StaticResource Locator}, Path=ViewAll}" x:Name="LayoutRoot" />

EDIT 2 This is the full code of the ViewModel

public class ViewAllViewModel : ViewModelBase
{
    public ViewAllViewModel()
    {
        NavigateToAddNew = new RelayCommand(() => NavigationController<Views>.Current.NavigateTo(Views.AddNew));
        Remove = new RelayCommand<int>(DeleteMeasure);

        LoadMeasures();

        Messenger.Default.Register<PropertyChangedMessage<ObservableCollection<Measure>>>(this, message => LoadMeasures());
    }

    private void LoadMeasures()
    {
        using (var repository = App.ServiceLocator.Get<IRepository>())
        {
            Measures = new ObservableCollection<Measure>(repository.Measures.OrderByDescending(m => m.MeasureDate).ThenByDescending(m => m.Id).Take(20));
        }
    }

    private void DeleteMeasure(int measureId)
    {
        Measure measure;

        using (IRepository repository = App.ServiceLocator.Get<IRepository>())
        {
            measure = repository.Measures.Single(m => m.Id == measureId);
            repository.Measures.Delete(measure);
            repository.SaveChanges();
        }

        measure = Measures.Single(m => m.Id == measureId);
        Measures.Remove(measure);

        RaisePropertyChanged("LastMeasure", null, measure, true);
    }

    public RelayCommand NavigateToAddNew { get; set; }
    public RelayCommand<int> Remove { get; set; }

    private ObservableCollection<Measure> _measures;
    public ObservableCollection<Measure> Measures
    {
        get { return _measures; }
        set { Set(() => Measures, ref _measures, value); }
    }
}
Kralizek
  • 1,999
  • 1
  • 28
  • 47
  • Does Measures.Remove(measure) return true? do you see your Measures getter fire again after the RaisePropertyChanged line? – William Melani Jun 23 '12 at 19:17
  • 2
    Can you show the code that is binding `ListBox.ItemsSource` to `Measures`? The only thing I can think of is something wrong with the binding. (Also, you shouldn't need to `RaisePropertyChanged` on the `Measures` collection after removing an item. The `ObservableCollection` automatically raises a `CollectionChanged` event when an item is removed, and will update the binding) – Rachel Jun 25 '12 at 19:05
  • I will as soon as I get home :) – Kralizek Jun 26 '12 at 07:12
  • for @Rachel: I finally managed to add the requested code. – Kralizek Jul 04 '12 at 21:56

1 Answers1

1

I don't see anything obviously wrong. All I can suggest is to try simplifying your ListBox to just this:

<ListBox Grid.Row="1" ItemsSource="{Binding Path=Measures}" />

And remove the code that calls RaisePropertyChanged(() => Measures); (since it should not be needed).

If neither of those work, I would test to see what happens if you completely reset your Measures property, as in:

private void DeleteMeasure(int measureId)
{
    using (IRepository repository = App.ServiceLocator.Get<IRepository>())
    {
        var measure = repository.Measures.Single(m => m.Id == measureId);
        repository.Measures.Delete(measure);
        repository.SaveChanges();
    }

    Measures = repository.Measures;
}

If that causes a successful refresh of the ListBox, it would imply that something is going on with the ObservableCollection.

devuxer
  • 41,681
  • 47
  • 180
  • 292