2012-06-04 5 views
11

Estoy trabajando en WPF y estoy usando un ListView, y necesito activar un evento cuando se agrega un elemento. He intentado esto:WPF: Levante un evento cuando se agrega un elemento en ListView

var dependencyPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ListView)); 
     if (dependencyPropertyDescriptor != null) 
     { 
       dependencyPropertyDescriptor.AddValueChanged(this, ItemsSourcePropertyChangedCallback); 
     } 

.....

private void ItemsSourcePropertyChangedCallback(object sender, EventArgs e) 
    { 
     RaiseItemsSourcePropertyChangedEvent(); 
    } 

pero parece estar funcionando solamente cuando se cambia toda la colección, He leído este post: event-fired-when-item-is-added-to-listview, pero la mejor respuesta se aplica solo a listBox. Traté de cambiar el código a ListView pero no pude hacer eso.

Espero que me puedas ayudar. Gracias de antemano.

+0

En los comentarios de respuesta a la pregunta que publique, encontrará "Modifiqué mi código anterior para que quede más claro. También esto debería funcionar con cualquier ItemsControl (ListBox o ListView). "- ¿Qué problema tienes en particular? – Slugart

+0

@Slugart Gracias por tu respuesta, el problema que tengo es que el método' BeginInvoke' no acepta la declaración como el ejemplo. Dice que 'DispatcherPriority' no existe – Dante

Respuesta

37

¡Tenga en cuenta que esto solo funciona para una lista de WPF!

Después de algunas investigaciones he encontrado la respuesta a mi pregunta y que es muy fácil:

public MyControl() 
{ 
    InitializeComponent(); 
    ((INotifyCollectionChanged)listView.Items).CollectionChanged += ListView_CollectionChanged; 
} 

private void ListView_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)  
{ 
    if (e.Action == NotifyCollectionChangedAction.Add) 
    { 
     // scroll the new item into view 
     listView.ScrollIntoView(e.NewItems[0]); 
    } 
} 

En realidad, el NotifyCollectionChangedAction enumeración permite a su programa para informarle acerca de cualquier cambio, como: añadir, mover, Reemplazar , Eliminar y Restablecer.

+1

Esto no funciona para mí. No puedo convertir el objeto de tipo 'ListViewItemCollection' para escribir 'System.Collections.Specialized.INotifyCollectionChanged'. –

+1

Para cualquier otra persona que tenga curiosidad, 'ListView.Items' es del tipo 'ItemsCollection'. Esto hereda de 'CollectionView' que implementa' INotifyCollectionChanged'. En cuanto a MSDN, esto fue cierto para .NET 3.0 - 4.6. @Arvo 'ListViewItemCollection' solo implementa' IList, ICollection, IEnumerable' y no hereda de nada, de ahí su excepción. –

+0

Funciona también con el Listbox de WPF. Si se une una observablecollection , ¡la primera aparición se verá en la vista! Entonces, si el mismo valor puede ocurrir varias veces, use una clase con una propiedad para vincular (observablecollection ) y configure DisplayMemberPath en consecuencia. – dba

-1

Nota: Esta solución se diseñó para un WinForms ListView.

En mi caso terminé llegando a un tenedor en la carretera con 2 opciones ...

(1) Crear un control ListView personalizado que hereda la clase de un ListView. A continuación, agregue un nuevo evento que se generará cuando se agregue, elimine o se borre ListView. Este camino parecía muy complicado y largo. Sin mencionar el otro gran problema que necesitaría para reemplazar todas mis ListViews originales con el control Custom ListView recién creado. ¡Así que pasé por esto!


(2) Con cada añadir, borrar, o una llamada clara a la vista de lista también llamado otra función que simula el evento CollectionChanged.

Crear nuevo evento como función ...

private void myListViewControl_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    //The projects ListView has been changed 
    switch (e.Action) 
    { 
     case NotifyCollectionChangedAction.Add: 
      MessageBox.Show("An Item Has Been Added To The ListView!"); 
      break; 
     case NotifyCollectionChangedAction.Reset: 
      MessageBox.Show("The ListView Has Been Cleared!"); 
      break; 
    } 
} 

Agregar un elemento a la ListView en otro lugar ...

ListViewItem lvi = new ListViewItem("ListViewItem 1"); 
lvi.SubItems.Add("My Subitem 1"); 
myListViewControl.Items.Add(lvi); 
myListViewControl_CollectionChanged(myListViewControl, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, lvi, lvi.Index)); 

Claro ListView en otro lugar ...

myListViewControl.Items.Clear(); 
myListViewControl_CollectionChanged(myListViewControl, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
+0

Es bastante extraño que la solución de Dante no funcione para usted, especialmente cuando su solución implica ... 'INotifyCollectionChanged'. '((INotifyCollectionChanged) MyList.Items) .CollectionChanged + = MyListChanged' funcionó para mí. ¿Estás seguro de poner el paréntesis en los lugares correctos? –

+0

Quizás tiene algo que ver con WPF, no uso eso, estoy usando WinForms. No estoy seguro, todo lo que sé es que se tienen en cuenta todos los espacios de nombres y todas las referencias funcionan perfectamente con esos objetos/tipos. Ni siquiera entiendo cómo podrías lanzar una colección de listView.Items a INotifyCollectionChanged (No digo que no se pueda hacer, simplemente no lo entiendo). Todo lo demás se ve bien excepto esa parte. Estoy más que dispuesto a intentar algo si me lo dices. Pero tal como está, mi VS 2010 dice ¡no! ;) –

+2

WinForms y WPF son dos bestias totalmente diferentes; ¡un 'ListView' de WinForms tiene ** nada ** que hacer con un' ListView' de WPF! El WPF 'ListViewItemCollection' implementa' INotifyCollectionChanged'; esto permite que las potentes capacidades de enlace de datos de WPF detecten cambios en la lista y [casi] * automágicamente * mantengan todo actualizado. Debería considerar dejar WinForms y probar WPF: una vez que lo domine, ¡nunca mirará hacia atrás! :) –

Cuestiones relacionadas