2009-05-08 34 views
5

Làm cách nào để ListCollectionView.AddNew xác định loại đối tượng mà đối tượng tạo và cách đối tượng có thể ảnh hưởng đến đối tượng đó?Loại đối tượng được tạo bởi ListCollectionView.AddNew

Tôi có một hệ thống phân cấp của một vài loại (Base, DerivedA, và DerivedB), và hiện tại tôi WPF Toolkit DataGrid tạo DerivedA đối tượng (tại sao, tôi không biết - có lẽ bởi vì hầu như tất cả các dữ liệu trong lưới là thuộc loại đó), nhưng tôi muốn nó tạo ra các đối tượng DerivedB thay thế.

Cập nhật: Tôi đã cố gắng phát sinh một lớp mới từ ListCollectionView và thực hiện một phương pháp mới AddNew cho nó, và bây giờ tôi gần như ở đó: vấn đề duy nhất còn lại là sau khi thêm một mục mới, mới mới mục giữ chỗ không được thêm vào, vì vậy tôi chỉ có thể thêm một mục. Cách tiếp cận hiện tại của tôi có vẻ hơi như thế này:

public class CustomView : ListCollectionView, IEditableCollectionView 
{ 
    public CustomView(System.Collections.IList list) 
     : base(list) 
    { 
    } 

    object IEditableCollectionView.AddNew() 
    { 
     DerivedB obj = new DerivedB(); 
     InternalList.Add(obj); 
     return obj; 
    } 
} 

Trả lời

4

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()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 BeginInitBeginEdit 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).

+0

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ó. –

+0

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. –

1

TomiJ,

xem nếu nó giúp, nhưng không phải là câu trả lời ok?

http://www.cnblogs.com/winkingzhang/archive/2008/05/22/1204581.html

+1

Bài viết (bài viết gốc có tại ) thuộc về một số trợ giúp, vì nó đã khiến tôi không nhìn vào 'ListCollectionView'. –

+0

Tôi hiểu, tôi đã quản lý để có được câu trả lời đúng, đừng quên cập nhật tại đây. Đó là một câu hỏi rất thú vị: D –

+0

Tôi chưa hoàn toàn ở đó, vì tôi chỉ có thể thêm _one_ mục mới, nhưng ít nhất chính xác phương thức AddNew được gọi. Tôi sẽ phải tìm ra những gì khác tôi cần phải thực hiện để có được chức năng thích hợp. –

1

Trong .NET 4, hiện tại có giao diện mới IEditableCollectionViewAddNewItem, được triển khai bởi ListCollectionView, có phương thức mới AddNewItem(object). Bạn có thể sử dụng nó thay vì AddNew() để kiểm soát mục mới được thêm vào.

+0

Thực tế là có, và câu trả lời này cũng không kém phần bình thường như câu trả lời từ Erikest mà tôi đã chấp nhận (bởi vì câu trả lời đó lớn hơn và cũng đề cập đến 'ListCollectionView.AddNewItem (object)'). –

Các vấn đề liên quan