ObservableCollection
Lớp Generic
ObservableCollection<T>
là một tập hợp tương tự như List<T>
...,
tức là nó mô tả một tập hợp dữ liệu có thể thay đổi số lượng bằng các phương thức quen thuộc như
Add()
, Remove()
, Clear()
...Nhưng với
ObservableCollection<T>
thì nó cung cấp thêm sự kiện thông báo nhi số lượng phần tử thay đổi
như thêm, bớt ...(nghĩa là giám sát được biến động phần tử).
Các sự kiện event này có tên là CollectionChanged
,
trong tham số mà sự kiện gửi đến, e.Action
có cho biết hành động thay đổi trên tập hợp là gì (ví dụ: thêm NotifyCollectionChangedAction.Add
, bớt NotifyCollectionChangedAction.Remove
), clear tập hợp NotifyCollectionChangedAction.Reset
...Ví dụ:
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; namespace CS019_ObserableCollection { class Program { static void Main(string[] args) { //Tạo tập hợp chứa các chuỗis ObservableCollectionobs = new ObservableCollection (); // Bắt sự kiện thi thay đổi obs obs.CollectionChanged += change; //Thay các phần tử tập hợp obs.Add("ZTest1"); obs.Add("DTest2"); obs.Add("ATest3"); obs[2] = "AAAAA"; obs.RemoveAt(1); obs.Clear(); } // Phương thức nhận sự kiện CollectionChanged private static void change(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (String s in e.NewItems) Console.WriteLine($"Thêm : {s}"); break; case NotifyCollectionChangedAction.Reset: Console.WriteLine("Clear"); break; case NotifyCollectionChangedAction.Remove: foreach (String s in e.OldItems) Console.WriteLine($"Remove : {s}"); break; case NotifyCollectionChangedAction.Replace: Console.WriteLine("Repaced - " + e.NewItems[0]); break; } } } }
Chạy thử, kết quả:
Add : Test1 Add : Test2 Add : Test3 Remove : Test2 Clear
Như vậy mỗi khi tập hợp obs thay phần tử, ta có thể bắt được ngày. Ứng dụng của
ObservableCollection
trong WPF rất phổ biến khi binding
với một controller như TreeView
, ListView
, DataGrid
... Khi đó việc thay đổi số phần tử trong tập hợp, thì hiện thị trong các controller cũng tự thêm / bớt ... theo. Khi bạn kết hợp dùng
INotifyPropertyChanged để xây dựng phần tử trong tập hợp, thì thay đổi thuộc tính của phần tử cũng tự động cập nhật vào các controllerTham khảo mã nguồn , hoặc tải về ex019
Khi dùng
ObservableCollection
làm ItemSource
cho các Controller trong WPF như TreeView, DataGrid ... thì nó đã tự động bắt các sự kiện CollectionChanged
, PropertyChanged
Ví dụ WPF dử dụng ObservableCollections
Chạy Visual Studio tạo ra một ứng dụng WPF đặt tên là
ObsExamps
Cập nhật
MainWindow.xaml
như sau<Window x:Class="ObsExamps.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ObsExamps" mc:Ignorable="d" Title="MainWindow" Height="450" Width="300"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <Button Content="Thêm" Margin="4,0" Click="Add" /> <Button Content="Xóa" Margin="4,0" Click="Remove"/> <Button Content="Xóa hết" Margin="4,0" Click="Clear"/> </StackPanel> <ListView Name="listview" Grid.Row="1"> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" /> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </Window>
Cập nhật
MainWindow.xaml.cs
như saupublic partial class MainWindow : Window { ObservableCollection<String> obs = new ObservableCollection<String>(); public MainWindow() { InitializeComponent(); //Thiết lập ItemsSource để Binding listview.ItemsSource = obs; } private void Add(object sender, RoutedEventArgs e) { obs.Add($"Mục mới thêm {obs.Count+1}"); } private void Remove(object sender, RoutedEventArgs e) { if (obs.Count > 0) obs.RemoveAt(obs.Count - 1); } private void Clear(object sender, RoutedEventArgs e) { obs.Clear(); } }
Hãy chạu thử ứng dụng, bấm vào các nút để thay đổi phần tử và ListView sẽ cập nhật theo. Từ ứng dụng này hãy sử dụng lớp Student
trong phần
INotifyPropertyChanged để hiện thị danh sách phần tử phức tạp hơn, khi phần tử nào đó thay đổi thuộc tính thì ListView cũng cập nhật theo