2

I'm trying to bind an ObservableCollection<T> to a DataGrid in WPF. Below the DataGrid, there are fields to edit the currently selected item from the DataGridlike so:

enter image description here

So the generic T of the ObservableCollection<T> has the following properties: - Title (Überschrift) - Description (Beschreibung) - Path (Pfad)

and it also has a property Reihenfolge which means Order.

With the yellow arrows, I want to be able to modify the order of the entries.

Unfortunately, the ObservableCollection doesn't have an OrderBy-method...


I've tried the following:

In XAML I have defined a CollectionViewSource like this:

<CollectionViewSource Source="{Binding Bilder}" x:Key="Pictures">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="Reihenfolge" />
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

And I have binded the DataGrid to this CollectionViewSource

<DataGrid Grid.Column="0" Grid.Row="1"
          Name="PictureDataGrid"  
          ItemsSource="{Binding Source={StaticResource Pictures}}"
          AutoGenerateColumns="False" 
          IsReadOnly="True" 
          CanUserAddRows="false" 
          SelectedItem="{Binding SelectedBild}"  
          HorizontalAlignment="Stretch" 
          VerticalAlignment="Stretch">
 ...

In the ViewModel, I have these properties:

public ObservableCollection<BildNotifiableModel> Bilder { get; set; }
public BildNotifiableModel SelectedBild { get; set; }

and two methods which are called with DelegateCommands that update the order

 private void MoveSeiteUp()
 {
     const int smallestReihenfolge = 1;
     if (this.SelectedBild.Reihenfolge > smallestReihenfolge) {
            var bildToSwapReihenfolgeWith = this.Bilder.Single(b => b.Reihenfolge == this.SelectedBild.Reihenfolge - 1);
            this.SelectedBild.Reihenfolge--;
            bildToSwapReihenfolgeWith.Reihenfolge++;

            RaisePropertyChanged(nameof(this.Bilder));
        }
    }

    private void MoveSeiteDown()
    {
        if (this.SelectedBild.Reihenfolge < MaxAllowedImages) {
            var bildToSwapReihenfolgeWith = this.Bilder.Single(b => b.Reihenfolge == this.SelectedBild.Reihenfolge + 1);
            this.SelectedBild.Reihenfolge++;
            bildToSwapReihenfolgeWith.Reihenfolge--;

            RaisePropertyChanged(nameof(this.Bilder));
        }
    }

The order gets updated correctly, but unfortunately, the view doesn't reflect the changes... only after closing and reopening the view, the entries in the DataGrid are in the correct order.

  • What am I doing wrong here?
  • How can I make the DataGrid update, when changing the order?

Thanks in advance

xeraphim
  • 4,375
  • 9
  • 54
  • 102
  • Instead of providing a translation of all your code, why not post a translated version here? – ChristianMurschall Sep 20 '18 at 11:37
  • To answer your question: [check this out](https://stackoverflow.com/a/5256827/4634044) – ChristianMurschall Sep 20 '18 at 11:44
  • The `ObservableCollection` class has a [Move](https://learn.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1.move?view=netframework-4.7.2) method which you should be able to use here. – mm8 Sep 20 '18 at 12:25
  • @ChristianMurschall this helped, thank you! If you add this as an answer, I'll accept it :) – xeraphim Sep 24 '18 at 06:58

2 Answers2

0

I think the problem is that the CollectionView doesn't listen for the PropertyChanged-Events from its elements and also RaisePropertyChanged(nameof(this.Bilder)); dosen't work because the CollectionView is not really changed.

I would recomend to create the CollectionView in code via CollectionViewSource.GetDefaultView(list). So you can control the CollectionView from your model and call ICollectionView.Refresh if needed.

Ackdari
  • 3,222
  • 1
  • 16
  • 33
0

In your Methods, create a new Collection and add it to "Bilder". Just raising the PropertyChanged will execute an evaluation for referential equality. If it is the same - which it will be, if you just move items inside around - it will not update the DataGrid.

If you are not using the ObservableCollections attributes, like automatically updates, when items are added or removed, you might also change it to a "normal" List.

private void MoveSeiteUp()
{
 const int smallestReihenfolge = 1;
 if (this.SelectedBild.Reihenfolge > smallestReihenfolge) {
        var bildToSwapReihenfolgeWith = this.Bilder.Single(b => b.Reihenfolge == this.SelectedBild.Reihenfolge - 1);
        this.SelectedBild.Reihenfolge--;
        bildToSwapReihenfolgeWith.Reihenfolge++;

        this.Bilder = new ObservableCollection<BildNotifiableModel> (this.Bilder);

        RaisePropertyChanged(nameof(this.Bilder));
    }
}

private void MoveSeiteDown()
{
    if (this.SelectedBild.Reihenfolge < MaxAllowedImages) {
        var bildToSwapReihenfolgeWith = this.Bilder.Single(b => b.Reihenfolge == this.SelectedBild.Reihenfolge + 1);
        this.SelectedBild.Reihenfolge++;
        bildToSwapReihenfolgeWith.Reihenfolge--;

        this.Bilder = new ObservableCollection<BildNotifiableModel> (this.Bilder);

        RaisePropertyChanged(nameof(this.Bilder));
    }
}
Andreas
  • 828
  • 4
  • 15