¿Alguien sabe por qué este código no funciona?
public class CollectionViewModel : ViewModelBase {
public ObservableCollection<EntityViewModel> ContentList
{
get { return _contentList; }
set
{
_contentList = value;
RaisePropertyChanged("ContentList");
//I want to be notified here when something changes..?
//debugger doesn't stop here when IsRowChecked is toggled
}
}
}
public class EntityViewModel : ViewModelBase
{
private bool _isRowChecked;
public bool IsRowChecked
{
get { return _isRowChecked; }
set { _isRowChecked = value; RaisePropertyChanged("IsRowChecked"); }
}
}
ViewModelBase
contiene todo para RaisePropertyChanged
etc. y funciona para todo lo demás excepto este problema.
c#
observablecollection
inotifypropertychanged
Joseph jun. Melettukunnel
fuente
fuente
Respuestas:
No se llamará al método Set de ContentList cuando cambie un valor dentro de la colección, en su lugar, debería estar atento al disparo del evento CollectionChanged .
Bien, eso es dos veces hoy. Me ha picado la documentación de MSDN que está equivocada. En el enlace que te di dice:
Pero en realidad no se dispara cuando se cambia un elemento. Supongo que necesitarás un método de fuerza bruta más entonces:
Si va a necesitar esto mucho, es posible que desee crear una subclase propia
ObservableCollection
que active elCollectionChanged
evento cuando un miembro active suPropertyChanged
evento automáticamente (como dice que debería en la documentación ...)fuente
changed
? Esto podría significar que una propiedad de uno de los elementos de la colección ha cambiado (que es como creo que la está interpretando) o podría significar que uno de los elementos de la colección ha cambiado al reemplazarlo con una instancia diferente ( Esta es mi interpretación). Sin embargo, no estoy totalmente convencido, tendrá que investigarlo más a fondo._contentList.Clear()
? ¡Nadie se dará de bajaPropertyChanged
!ContentCollectionChanged
solo maneja Agregar / Eliminar, y no Reemplazar / Restablecer. Intentaré editar y arreglar la publicación. La forma en que Simon lo hace en su respuesta es correcta.Aquí hay una clase desplegable que subclasifica ObservableCollection y en realidad genera una acción Restablecer cuando cambia una propiedad en un elemento de la lista. Aplica todos los elementos a implementar
INotifyPropertyChanged
.El beneficio aquí es que puede enlazar datos a esta clase y todos sus enlaces se actualizarán con cambios en las propiedades de su artículo.
fuente
NotifyCollectionChangedAction.Replace
no es una buena idea, porque no se puede distinguir entre un elemento que se está reemplazando o un evento causado por un cambio de elemento. Se pone mucho mejor cuando definepublic event PropertyChangedEventHandler CollectionItemChanged;
y luegoItemPropertyChanged
hacethis.CollectionItemChanged?.Invoke(sender, e);
He reunido lo que espero sea una solución bastante robusta, que incluya algunas de las técnicas en otras respuestas. Es una nueva clase derivada de la
ObservableCollection<>
que llamoFullyObservableCollection<>
Tiene las siguientes características:
ItemPropertyChanged
,. Deliberadamente he mantenido esto separado del existenteCollectionChanged
:ItemPropertyChangedEventArgs
que lo acompaña: el originalPropertyChangedEventArgs
y el índice dentro de la colección.ObservableCollection<>
.ObservableCollection<>.Clear()
), evitando una posible pérdida de memoria.OnCollectionChanged()
, en lugar de una suscripción más intensiva en recursos para elCollectionChanged
evento.Código
El
.cs
archivo completo sigue. Tenga en cuenta que se han utilizado algunas características de C # 6, pero debería ser bastante simple respaldarlo:NUnit Tests
Para que pueda verificar los cambios que pueda hacer (y ver lo que probé en primer lugar), también he incluido mi clase de prueba NUnit. Obviamente, el siguiente código no es necesario solo para usar
FullyObservableCollection<T>
en su proyecto.NB La clase de prueba utiliza
BindableBase
de PRISM para implementarINotifyPropertyChanged
. No hay dependencia en PRISM del código principal.fuente
ListView
responderá aCollectionChanged
los acontecimientos, ya que sabe acerca de ellos.ItemPropertyChanged
es una adición no estándar, por lo que debe enseñarle sobre eso. Como una solución rápida y sucia, podría intentar simplemente disparar elCollectionChanged
evento, así como (o incluso en lugar de)ItemPropertyChanged
enOnItemPropertyChanged()
. Los mantuve separados por las razones indicadas en la respuesta, pero para su caso de uso, podría hacer lo que necesita.Esto usa las ideas anteriores pero la convierte en una colección derivada 'más sensible':
fuente
ObservableCollection no propagará cambios de elementos individuales como eventos CollectionChanged. Deberá suscribirse a cada evento y reenviarlo manualmente, o puede consultar la clase BindingList [T] , que lo hará por usted.
fuente
Se agregó al evento TruelyObservableCollection "ItemPropertyChanged":
fuente
Utilicé la respuesta de Jack Kenyons para implementar mi propio OC, pero me gustaría señalar un cambio que tuve que hacer para que funcionara. En vez de:
Usé esto:
Parece que "e.NewItems" produce un valor nulo si la acción es .Remove.
fuente
Solo agrego mis 2 centavos sobre este tema. Sentí que TrulyObservableCollection requería los otros dos constructores que se encuentran con ObservableCollection:
fuente
Sé que llego demasiado tarde para esta fiesta, pero tal vez, ayudará a alguien ...
Aquí puede encontrar mi implementación de ObservableCollectionEx. Tiene algunas características:
Por supuesto, cualquier comentario es apreciado;)
fuente
Si conozco ObservableCollection, crea un evento solo cuando agregamos / eliminamos o movemos elementos en nuestra colección. Cuando simplemente actualizamos algunas propiedades en los elementos de la colección, la colección no señala al respecto y la interfaz de usuario no se actualizará.
Simplemente puede implementar INotifyPropertyChange en su clase de Modelo. Y cuando actualizamos algunas propiedades del elemento de colección, automáticamente actualizará la interfaz de usuario.
y que
En mi caso, utilicé ListView para enlazar para esta colección y en ItemTemplate establecí la propiedad Binding to Model y funcionó bien.
Aquí hay un fragmento
Windows XAML:
Ejemplo de código de modelo:
Y la implementación de ViewModel:
fuente
Solución simple para la colección estándar observable que he usado:
NO AGREGUE a su propiedad NI CAMBIE sus artículos internos DIRECTAMENTE, en su lugar, cree una colección temporal como esta
y agregue elementos o realice cambios en tmpList,
luego páselo a su propiedad real por asignación.
esto cambiará toda la propiedad, lo que provoca que se notifique INotifyPropertyChanged según lo necesite.
fuente
Intento esta solución, pero solo funciona para mí como un RaisePropertyChange ("SourceGroupeGridView") cuando se modifica la colección, que se activa para cada elemento agregado o modificado.
El problema está en:
NotifyCollectionChangedAction.Reset esta acción hace que un reenlace completo de todos los elementos en gridpedgled, sea equivalente en RaisePropertyChanged. Cuando lo usa, todos los grupos de gridview se actualizan.
SI solo desea actualizar en la interfaz de usuario el grupo del nuevo elemento, no utiliza la acción Restablecer, deberá simular una acción Agregar en itepertroperty con algo como esto:
Perdón por mi inglés, y gracias por el código base :), espero que esto ayude a alguien ^ _ ^
Enjoi !!
fuente
Aquí hay un método de extensión para la solución anterior ...
fuente
En lugar de una ObservableCollection o TrulyObservableCollection, considere usar una BindingList y llamar al método ResetBindings.
Por ejemplo:
Dado un evento, como un clic, su código se vería así:
Mi modelo se veía así:
fuente
BindingList
Hay buena información sobre este método , pero hay una limitación a este enfoque que las otras respuestas superan: esta técnica se basa en el valor que se cambia en el código y dondeResetBindings()
se puede agregar una llamada a . La mayoría de las otras respuestas funcionarán si los objetos de la lista se alteran por otros medios, como un código inalterable o desde un enlace a un segundo control.Para activar OnChange en la lista de colecciones observables
Ejemplo:
fuente
Aquí está mi versión de la implementación. Comprueba y arroja un error, si los objetos en la lista no implementan INotifyPropertyChanged, así que no puedo olvidar ese problema durante el desarrollo. En el exterior, usa el evento ListItemChanged para determinar si la lista o el elemento de la lista en sí han cambiado.
fuente
Solución simple en 2 líneas de código. Solo usa el constructor de copia. No es necesario escribir TrulyObservableCollection, etc.
Ejemplo:
Otro método sin constructor de copia. Puedes usar la serialización.
fuente
También puede usar este método de extensión para registrar fácilmente un controlador para el cambio de propiedad del elemento en colecciones relevantes. Este método se agrega automáticamente a todas las colecciones que implementan INotifyCollectionChanged que contienen elementos que implementan INotifyPropertyChanged:
Cómo utilizar:
fuente