domande Stale meritano nuove risposte :)
derivazione di una classe da ListCollectionView
è il percorso ho preso per controllare gli oggetti che viene aggiunto da AddNew
pure, ma dopo la navigazione attraverso la fonte di ListCollectionView
a scoprire che cosa fa internamente, ho trovato che il modo più sicuro per ridefinire AddNew
(non è tecnicamente un override) è usare ListCollectionView.AddNewItem
dopo aver creato il mio nuovo oggetto, quindi il tuo codice sarebbe il seguente:
public class CustomView : ListCollectionView, IEditableCollectionView
{
public CustomView(System.Collections.IList list)
: base(list)
{
}
object IEditableCollectionView.AddNew()
{
DerivedB obj = new DerivedB();
return base.AddNewItem(obj);
}
}
Questo funziona bene perché, oltre ad avere implementazioni quasi identiche altrimenti, ListCollectionView.AddNew()
e ListCollectionView.AddNewItem(object item)
sia chiamata 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
è dove tutta la vera magia accade; accensioni, chiamando BeginInit
e BeginEdit
sul nuovo elemento se supportato, e, infine, attraverso i callback sulla DataGrid, che stabilisce le associazioni di cella:
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;
}
Qui ho incluso il codice sorgente alla mia TypedListCollectionView
, che io uso per controllare il comportamento AddNew
quando non so che tipo saranno necessari in fase di progettazione:
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);
}
}
mi piace questo approccio in quanto offre la massima flessibilità per i casi in cui può avere bisogno di essere regolata in fase di esecuzione da AddNew
s' tipo uno all'altro. Permette anche a AddNew
di lavorare per aggiungere il primo elemento della collezione, il che è utile quando l'origine dell'elenco è inizialmente vuota, ma il suo tipo sottostante può essere determinato.
This link discute un modo alternativo per forzare il tipo utilizzato da AddNew()
. Usa la riflessione per impostare la proprietà privata _itemConstructor
utilizzata da AddNew
su un costruttore senza parametri di un tipo specificato.Questo sarebbe particolarmente utile quando il tuo ListCollectionView
proviene da un componente che è al di fuori della tua influenza, o hai bisogno di aggiungere funzionalità al codice esistente e sei preoccupato di rompere le cose (cosa che non sono mai perché sono un programmatore spregiudicato che insensibilmente cariati con collezioni).
Ho cambiato l'architettura nella mia applicazione, quindi questo non è più un problema per me, ma la tua risposta sembra plausibile basandoti solo a guardarla. –
Per qualche motivo, non ho accettato questa risposta l'anno scorso. –