C# Cơ bản .NET Core §1 Cài đặt, chương trình C# đầu tiên §2 Biến, kiểu dữ liệu và nhập/xuất §3 Toán tử số học và gán §4 So sánh, logic và lệnh if, switch §5 Vòng lặp for, while §6 Phương thức - Method §7 Chuyển số thành chữ §8 Phương thức - Delegate §9 Lớp - Class §10 Namespace §11 Partial, Nested §12 Kiểu giá trị, tham chiếu §13 Kiểu vô danh và dynamic §14 Biểu thức lambda §15 Event §16 Hàm hủy - Quá tải toán tử - thành viên tĩnh - indexer §17 null và nullable §18 Mảng §19 Chuỗi ký tự §20 Tính kế thừa §21 Phương thức khởi tạo §22 Tính đa hình - abstract - interface §23 Struct và Enum §24 Ngoại lệ Exeption §25 IDisposable - using §26 File cơ bản §27 FileStream §28 Generic §29 Collection - List §30 SortedList §31 Queue / Stack §32 Linkedlist §33 Dictionary - HashSet §34 Phương thức mở rộng §35 ObservableCollection §36 LINQ §37 (Multithreading) async - bất đồng bộ §38 Type §39 Attribute Annotation §40 DI Dependency Injection §41 (Multithreading) Parallel §42 Thư viện lớp §43 (Networking) Uri, Dns, Ping §44 (Networking) HttpClient §45 (Networking) HttpMessageHandler §46 (Networking) HttpListener §47 (Networking) Tcp TcpListenerr/TcpClient §48 (ADO.NET) SqlConnection §49 (ADO.NET) SqlCommand §50 (ADO.NET) DataAdapter §51 (EF Core) Tổng quan §52 (EF Core) Tạo Model §53 (EF Core) Fluent API §54 (EF Core) Query §55 (EF Core) Scaffold §56 (EF Core) Migration §57 (ASP.NET CORE) Hello World! §58 (ASP.NET CORE) Middleware §59 (ASP.NET CORE) Map - Request - Response §60 (ASP.NET CORE) IServiceCollection - MapWhen §61 (ASP.NET CORE) Session - ISession §62 (ASP.NET CORE) Configuration §63 (ASP.NET CORE) Gửi Mail §64 (ASP.NET CORE) SASS/SCSS §65 (ASP.NET CORE) LibMan §66 (ASP.NET RAZOR) Khởi tạo và Route §67 (ASP.NET RAZOR) Cú pháp Razor §68 (ASP.NET RAZOR) Layout trong ASP.NET Core §69 (ASP.NET RAZOR) Partial §70 (ASP.NET RAZOR) ViewComponent §71 (ASP.NET RAZOR) TagHelper §72 (ASP.NET RAZOR) HtmlHelper §73 (ASP.NET RAZOR) PageModel §74 (ASP.NET RAZOR) Model Binding §75 (ASP.NET RAZOR) HTML Form, Validation §76 (ASP.NET RAZOR) Upload File §77 (ASP.NET RAZOR) Entity Framework §78 (ASP.NET RAZOR) Paging §79 (ASP.NET RAZOR) Identity (1) - Register, Login, Logout §80 (ASP.NET RAZOR) Identity (2) Lockout, Reset Password §81 (ASP.NET RAZOR) Identity (3) Google Login §82 (ASP.NET RAZOR) Identity (4) Facebook Login §83 (ASP.NET RAZOR) Identity (5) profile, password, email ... §84 (ASP.NET RAZOR) Identity (6) Role §85 (ASP.NET RAZOR) Identity (7) Role-based Authorization §86 (ASP.NET RAZOR) Identity (8) RoleClaim §87 (ASP.NET RAZOR) Identity (9) Authorization Handler §88 (ASP.NET RAZOR) IAuthorizationService §89 (ASP.NET MVC) Controller - View §90 (ASP.NET MVC) Route §91 (ASP.NET MVC) EF, Identity §92 (ASP.NET MVC) Binding, Validation §93 (ASP.NET MVC) Xây dựng Website(1) §94 (ASP.NET MVC) Xây dựng Website(2) §95 (ASP.NET MVC) Xây dựng Website(3) §96 (ASP.NET MVC) Xây dựng Website(4) §97 (ASP.NET MVC) Giỏ hàng - Cart (5) §98 (ASP.NET MVC) elFinder (5) §99 (ASP.NET MVC) SB Admin (6) §100 (ASP.NET MVC) Kestrel, publish
Lập trình C# Cơ bản
(Bài tiếp) LINQ

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
            ObservableCollection obs = 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 controller

Tham 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ư sau
public 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

(Bài tiếp) LINQ