preguntas rancios merecen respuestas frescas :)
derivar una clase a partir de ListCollectionView
es el camino que tomé para controlar los objetos que se añaden por AddNew
también, pero después de navegar a través de la fuente de ListCollectionView
a averiguar lo que hace internamente, encontré que la forma más segura de redefinir AddNew
(técnicamente no es una anulación) es usar ListCollectionView.AddNewItem
después de crear mi nuevo objeto, para que su código se vea así:
public class CustomView : ListCollectionView, IEditableCollectionView
{
public CustomView(System.Collections.IList list)
: base(list)
{
}
object IEditableCollectionView.AddNew()
{
DerivedB obj = new DerivedB();
return base.AddNewItem(obj);
}
}
Esto funciona bien porque, además de tener implementaciones casi idénticas de otro modo, ListCollectionView.AddNew()
y ListCollectionView.AddNewItem(object item)
tanto llamada AddNewCommon(object newItem)
:
public object AddNew()
{
VerifyRefreshNotDeferred();
if (IsEditingItem)
{
CommitEdit(); // implicitly close a previous EditItem
}
CommitNew(); // implicitly close a previous AddNew
if (!CanAddNew)
throw new InvalidOperationException(SR.Get(SRID.MemberNotAllowedForView, "AddNew"));
return AddNewCommon(_itemConstructor.Invoke(null));
}
public object AddNewItem(object newItem)
{
VerifyRefreshNotDeferred();
if (IsEditingItem)
{
CommitEdit(); // implicitly close a previous EditItem
}
CommitNew(); // implicitly close a previous AddNew
if (!CanAddNewItem)
throw new InvalidOperationException(SR.Get(SRID.MemberNotAllowedForView, "AddNewItem"));
return AddNewCommon(newItem);
}
AddNewCommon
es donde sucede toda la magia real; arranques, llamando BeginInit
y BeginEdit
en el nuevo elemento si es compatible, y, finalmente, a través de devoluciones de llamada en la cuadrícula de datos, estableciendo los enlaces celulares:
object AddNewCommon(object newItem)
{
_newItemIndex = -2; // this is a signal that the next Add event comes from AddNew
int index = SourceList.Add(newItem);
// if the source doesn't raise collection change events, fake one
if (!(SourceList is INotifyCollectionChanged))
{
// the index returned by IList.Add isn't always reliable
if (!Object.Equals(newItem, SourceList[index]))
{
index = SourceList.IndexOf(newItem);
}
BeginAddNew(newItem, index);
}
Debug.Assert(_newItemIndex != -2 && Object.Equals(newItem, _newItem), "AddNew did not raise expected events");
MoveCurrentTo(newItem);
ISupportInitialize isi = newItem as ISupportInitialize;
if (isi != null)
{
isi.BeginInit();
}
IEditableObject ieo = newItem as IEditableObject;
if (ieo != null)
{
ieo.BeginEdit();
}
return newItem;
}
Aquí he incluido el código fuente para mi TypedListCollectionView
, que utilizo para controlar el comportamiento AddNew
cuando no sé qué tipo será necesaria en tiempo de diseño:
public class TypedListCollectionView : ListCollectionView, IEditableCollectionView
{
Type AddNewType { get; set; }
public TypedListCollectionView(System.Collections.IList source, Type addNewType)
: base(source)
{
AddNewType = addNewType;
}
object IEditableCollectionView.AddNew()
{
object newItem = Activator.CreateInstance(AddNewType);
return base.AddNewItem(newItem);
}
}
me gusta este enfoque, ya que proporciona la máxima flexibilidad para los casos en que puede necesitar ser ajustados en tiempo de ejecución de AddNew
's tipo de uno a otro. También permite que AddNew
funcione para agregar el primer elemento de la colección, lo que es útil cuando el origen de la lista está inicialmente vacío, pero se puede determinar su tipo subyacente.
This link se describe una forma alternativa de forzar el tipo utilizado por AddNew()
. Utiliza la reflexión para establecer la propiedad privada _itemConstructor
utilizada por AddNew
en un constructor sin parámetros de un tipo especificado.Esto sería particularmente útil cuando su ListCollectionView
proviene de un componente que está fuera de su influencia, o necesita agregar funcionalidad al código existente y está preocupado por romper las cosas (lo que nunca sucede porque soy un codicioso codificador que con insensibilidad) Cansos con colecciones).
Cambié la arquitectura de mi aplicación, así que esto ya no es un problema para mí, pero su respuesta parece plausible basándome en solo mirarla. –
Por alguna razón, no parece haber aceptado esta respuesta el año pasado. –