views:

547

answers:

2

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
    }
}
+2  A: 

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.

Scott Dorman
Main points look correct, just thought I should point out that moving an item to a lower index will not work with this code - the this.Remove(item) will shift the indexes. At the least you insert your item one-off, at worst, you try to insert past the end of the list.
Yoopergeek
A: 

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.

Gary Mason