câu hỏi thiu xứng đáng câu trả lời trong lành :)
Thu được một lớp từ ListCollectionView
là con đường tôi đã kiểm soát các đối tượng được bổ sung bởi AddNew
là tốt, nhưng sau khi duyệt qua các nguồn ListCollectionView
để tìm ra nội dung trong nội bộ, tôi thấy rằng cách an toàn nhất để xác định lại AddNew
(không phải là ghi đè kỹ thuật) là sử dụng ListCollectionView.AddNewItem
sau khi tạo đối tượng mới, vì vậy mã của bạn sẽ trông như sau:
public class CustomView : ListCollectionView, IEditableCollectionView
{
public CustomView(System.Collections.IList list)
: base(list)
{
}
object IEditableCollectionView.AddNew()
{
DerivedB obj = new DerivedB();
return base.AddNewItem(obj);
}
}
này hoạt động tốt bởi vì, ngoài việc triển khai gần như giống hệt cách khác, ListCollectionView.AddNew()
và ListCollectionView.AddNewItem(object item)
cả cuộc gọi 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
là nơi tất cả các kỳ diệu thực sự xảy ra; bắn các sự kiện, gọi BeginInit
và BeginEdit
vào mục mới nếu được hỗ trợ, và cuối cùng thông qua callbacks trên DataGrid, thiết lập các ràng buộc tế bào:
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;
}
Ở đây tôi đã bao gồm các mã nguồn để TypedListCollectionView
của tôi, mà tôi sử dụng để kiểm soát hành vi AddNew
khi tôi không biết những gì loại sẽ là cần thiết vào thời điểm thiết kế:
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);
}
}
tôi thích phương pháp này vì nó cung cấp sự linh hoạt tối đa cho trường hợp AddNew
's loại có thể cần phải được điều chỉnh trong thời gian chạy từ cái khác. Nó cũng cho phép AddNew
làm việc để thêm mục đầu tiên vào bộ sưu tập, điều này rất thuận tiện khi nguồn danh sách ban đầu trống, nhưng loại cơ bản của nó có thể được xác định.
This link thảo luận một cách khác để buộc loại được sử dụng bởi AddNew()
. Nó sử dụng sự phản chiếu để thiết lập thuộc tính private _itemConstructor
được sử dụng bởi AddNew
cho một hàm tạo parameterless của một kiểu được chỉ định.Điều này sẽ đặc biệt hữu ích khi ListCollectionView
của bạn đến từ một thành phần ngoài tầm ảnh hưởng của bạn, hoặc bạn cần thêm chức năng vào mã hiện có và bạn lo lắng về việc phá vỡ mọi thứ (mà tôi không bao giờ là vì tôi là carouses với bộ sưu tập).
Tôi đã thay đổi kiến trúc trong ứng dụng của mình vì vậy đây không còn là vấn đề đối với tôi, nhưng câu trả lời của bạn có vẻ hợp lý dựa trên việc xem xét nó. –
Vì lý do nào đó, tôi dường như không chấp nhận câu trả lời này năm ngoái. –