Eric Anastas
Eric Anastas

Reputation: 22223

What causes a ListChangedType.ItemMoved ListChange Event in a BindingList<T>?

I have a BindingList(T) that I am displaying in a DataGrid. I'm watching for ListChanged events and performing different actions when the ListChanged event is evoked.

I'm checking the ListChangeType argument of the event to check how the list was changed, and then responding accordingly. However, I noticed that there is a ListChanged event type ItemMoved.

I have buttons for "Move Up" and "Move Down" to move items up and down the list. But these are actually removing the selected item, and then reinserting it at a higher or lower position.

However, I don't see any method of BindingList(T) that looks like it would move an item in the list. So am I missing something or is there just no way to move an item in a BindingList that would also evoke a ItemMoved type ListChanged event?

void FloorCollection_ListChanged(object sender, ListChangedEventArgs e)
{
    if (e.ListChangedType == ListChangedType.ItemAdded)
    {    
        //DO STUFF
    }
    else if (e.ListChangedType == ListChangedType.ItemDeleted)
    {
        //DO STUFF
    }
    else if (e.ListChangedType == ListChangedType.ItemMoved)
    {
        //HOW DO I GET THIS CODE TO RUN?
    }
    else if (e.ListChangedType == ListChangedType.ItemChanged)
    {
        //DO STUFF
    }
}

Upvotes: 13

Views: 4265

Answers (3)

Scott Dorman
Scott Dorman

Reputation: 42516

Unfortunately, nothing in BindingList will raise a ListChanged event with ListChangedType set to ListChangedType.ItemMoved. BindingList inherits from Collection which does not provide any kind of support for "moving" items in the list. BindingList does not add any support for this type of behavior either.

If you really need/want to respond the ListChangedType.ItemMoved events your best option is to derive your own class from BindingList and provide your own Move methods. Inside those methods you need to temporarily suspend raising ListChanged events, perform the move by removing/adding, raise the ListChanged event yourself with the appropriate ItemMoved ListChangedType, and then revert the suspension of raising ListChanged events.

It would look something like this*:

public class CustomBindingList<T> : BindingList<T>
{
   public void Move(T item, int index)
   {
      bool raiseListChangedEvents = this.RaiseListChangedEvents;
      try
      {
         this.RaiseListChangedEvents = false;
         int oldIndex = this.IndexOf(item);
         this.Remove(item);
         this.InsertItem(index, item);    
         this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemMoved, index, oldIndex));
      }
      finally
      {
         this.RaiseListChangedEvents = raiseListChangedEvents;
      }
   }
}

*Totally untested code, but it should illustrate the main points.

Upvotes: 12

Dwighte
Dwighte

Reputation: 496

Along similar lines to Scott's answer, you could do something like this extension method:

//Dumping ground for miscellaneous functions
public static class Misc
{
   //Swap items at index positions 'index0' and 'index1' in the list
   public static void Swap<T>(this BindingList<T> list, int index0, int index1, bool reset_bindings)
   {
      if (index0 == index1) return;
      bool raise_events = list.RaiseListChangedEvents;
      try
      {
         list.RaiseListChangedEvents = false;
         T tmp = list[index0];
         list[index0] = list[index1];
         list[index1] = tmp;
         list.RaiseListChangedEvents = raise_events;
         if (reset_bindings) list.ResetBindings();
      }
      finally
      {
         list.RaiseListChangedEvents = raise_events;
      }
   }
}

This doesn't produce the ItemMoved events you were after but saves having to subclass BindingList<>. You can raise the Reset event (using ResetBindings()) once you've finished moving items in the list. Might be helpful...

Upvotes: 1

Gary Mason
Gary Mason

Reputation: 11

It triggers if the binding source has a sort applied to it, if you change and data that is held in the sort field and it then changes the position of the record then the event triggers.

Upvotes: 1

Related Questions