2012-06-04 35 views
11

Tôi đang làm việc trên WPF và tôi đang sử dụng ListView và tôi cần kích hoạt sự kiện khi một mục được thêm vào nó. Tôi đã cố gắng này:WPF: Tăng sự kiện khi mục được thêm vào trong ListView

var dependencyPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(ListView)); 
     if (dependencyPropertyDescriptor != null) 
     { 
       dependencyPropertyDescriptor.AddValueChanged(this, ItemsSourcePropertyChangedCallback); 
     } 

.....

private void ItemsSourcePropertyChangedCallback(object sender, EventArgs e) 
    { 
     RaiseItemsSourcePropertyChangedEvent(); 
    } 

Nhưng Nó dường như được làm việc chỉ khi toàn bộ bộ sưu tập được thay đổi, Tôi đã đọc bài này: event-fired-when-item-is-added-to-listview, nhưng câu trả lời tốt nhất chỉ áp dụng cho một ListBox. Tôi đã cố gắng để thay đổi mã để ListView nhưng tôi đã không thể làm điều đó.

Tôi hy vọng Bạn có thể giúp tôi. Cảm ơn bạn trước.

+0

Trong các ý kiến ​​trả lời cho câu hỏi bạn đăng, bạn sẽ tìm thấy "Sửa đổi mã của tôi ở trên để làm cho nó rõ ràng hơn. Ngoài ra điều này sẽ làm việc với bất kỳ ItemsControl (ListBox hoặc ListView). "- Vấn đề gì là bạn có đặc biệt? – Slugart

+0

@ Slugart Cảm ơn bạn đã trả lời của bạn, vấn đề tôi có là phương pháp' BeginInvoke' không chấp nhận khai báo là Nó nói rằng 'DispatcherPriority' không tồn tại – Dante

Trả lời

37

Lưu ý rằng thao tác này chỉ hoạt động đối với Chế độ xem danh sách WPF!

Sau khi một số nghiên cứu tôi đã tìm thấy câu trả lời cho câu hỏi của tôi và nó thực sự dễ dàng:

public MyControl() 
{ 
    InitializeComponent(); 
    ((INotifyCollectionChanged)listView.Items).CollectionChanged += ListView_CollectionChanged; 
} 

private void ListView_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)  
{ 
    if (e.Action == NotifyCollectionChangedAction.Add) 
    { 
     // scroll the new item into view 
     listView.ScrollIntoView(e.NewItems[0]); 
    } 
} 

Trên thực tế, NotifyCollectionChangedAction enum cho phép chương trình của bạn để thông báo cho bạn biết về bất kỳ sự thay đổi như: Thêm, di chuyển, thay thế , Xóa và Đặt lại.

+1

Điều này không làm việc cho tôi. Tôi nhận được Không thể bỏ đối tượng thuộc loại 'ListViewItemCollection' để gõ 'System.Collections.Specialized.INotifyCollectionChanged'. –

+1

Đối với bất kỳ ai tò mò, 'ListView.Các mục' thuộc loại 'ItemsCollection'. Điều này kế thừa từ 'CollectionView' mà thực hiện' INotifyCollectionChanged'. Nhìn vào MSDN, điều này đúng với .NET 3.0 - 4.6. @Arvo 'ListViewItemCollection' chỉ thực hiện' IList, ICollection, IEnumerable' và không kế thừa từ bất cứ điều gì, do đó ngoại lệ của bạn. –

+0

Làm việc với WPF Listbox quá. Nếu quan sát bị ràng buộc, sự xuất hiện đầu tiên sẽ được đưa vào Xem! Vì vậy, nếu cùng một giá trị có thể xảy ra nhiều lần, hãy sử dụng một lớp với một thuộc tính để liên kết (observablecollection ) và đặt DisplayMemberPath tương ứng. – dba

-1

Lưu ý: Giải pháp này có nghĩa là cho một ListView WinForms.

Trong trường hợp của tôi, tôi đã kết thúc khi đến một ngã ba đường với 2 lựa chọn ...

(1) Tạo một điều khiển ListView tùy chỉnh mà kế thừa lớp một của ListView. Sau đó, thêm một sự kiện mới được nâng lên khi bất kỳ mục nào được thêm, xóa hoặc ListView sẽ bị xóa. Con đường này dường như thực sự lộn xộn và dài. Chưa kể đến vấn đề lớn khác mà tôi sẽ cần phải thay thế tất cả các ListView gốc của tôi bằng điều khiển Custom ListView mới được tạo ra. Vì vậy, tôi đã thông qua điều này!


(2) Với mỗi thêm, xóa, hoặc gọi rõ ràng đối với listview tôi cũng kêu gọi một chức năng mô phỏng sự kiện CollectionChanged.

Tạo sự kiện mới như chức năng ...

private void myListViewControl_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    //The projects ListView has been changed 
    switch (e.Action) 
    { 
     case NotifyCollectionChangedAction.Add: 
      MessageBox.Show("An Item Has Been Added To The ListView!"); 
      break; 
     case NotifyCollectionChangedAction.Reset: 
      MessageBox.Show("The ListView Has Been Cleared!"); 
      break; 
    } 
} 

Thêm một mục vào ListView nơi khác ...

ListViewItem lvi = new ListViewItem("ListViewItem 1"); 
lvi.SubItems.Add("My Subitem 1"); 
myListViewControl.Items.Add(lvi); 
myListViewControl_CollectionChanged(myListViewControl, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, lvi, lvi.Index)); 

Xóa ListView nơi khác ...

myListViewControl.Items.Clear(); 
myListViewControl_CollectionChanged(myListViewControl, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
+0

Thật kỳ lạ khi giải pháp của Dante không hiệu quả với bạn, đặc biệt là khi công việc của bạn liên quan đến ... 'INotifyCollectionChanged'. '((INotifyCollectionChanged) MyList.Items) .CollectionChanged + = MyListChanged' làm việc cho tôi. Bạn có chắc chắn đặt dấu ngoặc đơn ở đúng vị trí không? –

+0

Có lẽ nó có một cái gì đó để làm với WPF, tôi không sử dụng, tôi đang sử dụng WinForms. Không chắc chắn, tất cả những gì tôi biết là tất cả các không gian tên đều được tính toán và tất cả các tham chiếu đều hoạt động hoàn hảo với các đối tượng/kiểu đó. Tôi thậm chí không thực sự có được làm thế nào bạn có thể đúc một bộ sưu tập của listView.Items để INotifyCollectionChanged (Không nói nó không thể được thực hiện, tôi chỉ không nhận được nó). Mọi thứ khác có vẻ tốt ngoại trừ phần đó. Tôi sẽ sẵn sàng thử một cái gì đó nếu bạn nói với tôi. Nhưng khi nó đứng VS 2010 của tôi nói không! ;) –

+2

WinForms và WPF là hai con thú hoàn toàn khác nhau; một WinForms 'ListView' có ** không có gì ** để làm với một WPF' ListView'! WPF 'ListViewItemCollection' thực thi' INotifyCollectionChanged'; điều này cho phép khả năng ràng buộc dữ liệu mạnh mẽ của WPF để phát hiện các thay đổi trong danh sách và [gần như] * tự động * giữ mọi thứ cập nhật. Bạn nên xem xét để lại WinForms phía sau và thử WPF - một khi bạn nhận được hang của nó, bạn sẽ không bao giờ nhìn lại! :) –

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