How to update ObservableCollection in codeBehind a

2019-08-19 08:21发布

问题:

I am having some difficulty when I use the Josh Smith's issue for DnD on listView.

I have an ObservableCollection of "DetailTable" that I initialize in the ViewModel when I create the view :

(ListeTables is CollectionViewSource where I initialize and use my data)

public ObservableCollection<DetailTable> ListeTablesDisplay
{
    get
    {
        var l = ListeTables.View.Cast<DetailTable>().ToList();
        return new ObservableCollection<DetailTable>(l);
    }
}

The listView in the Xaml file :

    <ListView Name="ListeViewTables" SelectionMode="Single" 
              AllowDrop="true"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
              ItemsSource="{Binding ListeTablesDisplay, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
              SelectedItem="{Binding SelectedTable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
              Margin="10,83,831,61">

And then I call the Class of Josh Smith for the DnD in the View CodeBehind :

public DataView()
{
    InitializeComponent();

    new ListViewDragDropManager<DetailTable>(this.ListeViewTables);
}

Until now, the drag and drop work correctly, but in the ViewModel the order of items of the ObservableCollection is not coherent with what I do in the View.

Example : if I move the item-3 to the 5th position, it's ok with the View but when I debug I see the item-3 always to the 3rd position in my ObservableCollection.

It's very problematic for what I want to do, I hope someone can help me !

Thanks

回答1:

If a person has the same problem, just add the event ProcessDrop on ListViewDragDropManager

Then in the viewModel the event need to move manually the item index in the ObservableCollection

    public static void OnProcessDrop(object sender, ProcessDropEventArgs<T> e)
    {
        e.ItemsSource.Move(e.OldIndex, e.NewIndex);

        e.Effects = DragDropEffects.Move;
    }

Here an example by the autor of ListViewDragDropManager - "Custom drop logic" for help



回答2:

Here's how to handle this in the general case. OP was able to get it to work as desired with Smith's code by handling Smith's ProcessDrop event.

In the drop handler, determine whether the target ListView's ItemsSource is null.

If you have an ItemsSource, cast it to System.Collections.IList and do the reordering operation on the list, not on Items. Forget Items in this branch. If the items source is an ObservableCollection<T>, the ordering in the ListView will update. If it isn't, that's not your problem. The consumer of your code who provided the wrong list type needs to post a question asking why WPF doesn't get change notifications from List<T> or int[] or String or whatever.

If you don't have an ItemsSource, you just have ListViewItems. Reorder Items. Easy.

I've never before seen Josh Smith's code, and he'd be the guy to talk to if you need updates. Personally, I use an Adorner rather than restyling the list control items, but you can make a case for either approach.