Prism Library 5.0 for WPF – Triển khai mô hình MVVM

Mô hình Model-View-ViewModel (MVVM) giúp bạn tách riêng business và presentation logic của ứng dụng khỏi giao diện người dùng (UI).

Các bài liên quan

  1. Prism là gì ? các khái niệm chính trong Prism Library 5.0 for WPF
  2. Prism Library 5.0 for WPF – Khởi tạo ứng dụng
  3. Prism Library 5.0 for WPF – Implementing MVVM Pattern
  4. Prism Library 5.0 for WPF – Sử dụng Event Aggregation xây dựng một composite application

Hình minh họa dưới đây cho thấy ba lớp MVVM và tương tác của chúng.

 MVVM classes

Bài viết này mình chỉ tập trung dịch và giới thiệu các việc Implementing MVVM Pattern theo Prism Library. Các bạn có thể tham khảo bài viết sau để hiểu chi tiết về MVVM: WPF MVVM step by step (Basics to Advance Level)

View Class

  1. Là nơi chứa các visual element, như window, page, user control,..
  2. View tham chiếu đến View Model thông qua DataContext property.
  3. Bạn có thể sử dụng converters để custom lại giá trị được binding từ View Model lên View. xem thêm converters ở đây 
  4. code-behind của view nên được dùng để đinh nghĩa các code login liên quan đến giao diện hoặc các chức năng liên quan đến giao diện mà bạn khó tthuwjc hiện bằng xaml

View Model Class

  1. implement các properties và command mà view có thể data bind.Nó thông báo cho view bất cứ state changes thông qua notification events thông qua INotifyPropertyChanged và  INotifyCollectionChanged interfaces.
  2. Nó cũng có thể đùng để implement data validation thông qua IDataErrorInfo hoặc  INotifyDataErrorInfo interfaces.
  3. View model có thể định nghĩa các trạng thái logic mà view thể hiện trực quan cho người dùng.

Data context

Bạn cũng có thể chỉ định trong XAML rằng view model được thiết lập cho view thông qua data context.

<UserControl.DataContext>
    <my:MyViewModel/>
</UserControl.DataContext>

hoặc từ code của view

public MyView()
{
    InitializeComponent();
    this.DataContext = new MyViewModel();
}

Tương tác giữa các class

Sự tương tác giữa View và View model của nó có lẽ là điều quan trọng nhất cần xem xét nhưng sự tương tác giữa ModelView model cũng rất quan trọng.

Data Binding

Chúng ta sử dụng data binding để tương tác 1 properties giữa View và Viewmodel. có thể nói dễ hiểu là bạn có 1 properties ở view model bạn muốn nó hiện vào 1 Textbox trên view và khi người ta nhập liệu trên view bạn muốn giá trị đó được gán xuống view model. Các bạn có thể xem giải thích chi tiết ở đây

Implementing INotifyPropertyChanged

Thư viện Prism cung cấp lớp cơ sở BindableBase, từ đó bạn có thể implement INotifyPropertyChanged interface một cách an toàn, như được hiển thị ở đây.

public abstract class BindableBase : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;
   ...
   protected virtual bool SetProperty(ref T storage, T value, 
                          [CallerMemberName] string propertyName = null)
   {...}
   protected void OnPropertyChanged(
                          Expression<Func> propertyExpression)
   {...}
 
   protected void OnPropertyChanged(string propertyName)
   {...}
}

Để khai báo 1 propeties bạn tham khảo code như bên dưới

public TransactionInfo TransactionInfo
{
    get { return this.transactionInfo; } 
    set 
    { 
         SetProperty(ref this.transactionInfo, value); 
         // nếu muốn raised PropertyChanged cho thuộc tính TickerSymbol
         this.OnPropertyChanged(() => this.TickerSymbol);
    }
}

Implementing INotifyCollectionChanged

Trong nhiều trường hợp chúng ta cần binding một danh sách lên view.   khi đó bạn sẽ binding thông qua ItemSource property.

<DataGrid ItemsSource="{Binding Path=LineItems}" />

Và cách danh sách các bạn nên implement theo INotifyCollectionChanged interface, tức là chúng ta sẽ sử dụng ObservableCollection<T> . Bởi vì lớp ObservableCollection <T> implement INotifyCollectionChanged interface, các điều khiển trong view sẽ được tự động cập nhật để phản ánh danh sách hiện tại khi có item được thêm vào hoặc xoá. Tham khảo code bên dưới.

public class OrderViewModel : BindableBase
{
    public OrderViewModel( IOrderService orderService )
    {
        this.LineItems = new ObservableCollection(
                               orderService.GetLineItemList() );
    }

    public ObservableCollection LineItems { get; private set; }
}

Implementing ICollectionView

Khi bạn cần ncho phép danh sách được filter hoặc sort hoặc bạn cần track selected item trong view để commands trong view model có thể hành động theo selected item hiện tại.
WPF hỗ trợ các kịch bản này bằng cách cung cấp các lớp khác nhau thực hiện giao diện ICollectionView. Giao diện này cung cấp các thuộc tính và phương pháp để cho phép danh sách được lọc, sắp xếp hoặc nhóm và cho phép theo dõi hoặc thay đổi mục được chọn hiện tại. WPF cung cấp một sự thực hiện của giao diện này bằng cách sử dụng lớp ListCollectionView.

Trong WPF, một khung nhìn mặc định sẽ được tự động tạo ra bất cứ khi nào control được ràng buộc với một danh sách.

Ví dụ mã sau đây cho thấy việc sử dụng ListCollectionView trong WPF để theo dõi khách hàng hiện đang được chọn.

public class MyViewModel : BindableBase
{
    public ICollectionView Customers { get; private set; }

    public MyViewModel( ObservableCollection customers )
    {
        // Initialize the CollectionView for the underlying model
        // and track the current selection.
        Customers = new ListCollectionView( customers );
        
        Customers.CurrentChanged +=SelectedItemChanged;
    }

    private void SelectedItemChanged( object sender, EventArgs e )
    {
        Customer current = Customers.CurrentItem as Customer;
        ...
    }
    ...

Ở View

<ListBox ItemsSource="{Binding Path=Customers}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Path=Name}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Commands

khi chúng ta cần implement một action nào đó con control mà gọi xuống view model chúng ta sẽ dùng Commands. ví dụ click vào 1 nút, chọn giá trị trong dropdownlist.

Để khai báo commands  bạn tham khỏa code sau

public class QuestionnaireViewModel
{
    public QuestionnaireViewModel()
    {
       this.SubmitCommand = new DelegateCommand(this.OnSubmit, this.CanSubmit );
    }
 
    public ICommand SubmitCommand { get; private set; }

    private void OnSubmit()   
    {
    ///implement xử lý ở đây
    }
    private bool CanSubmit()  
    { 
       // có thể dùng để validate
       return true; 
    }
}

Trên view

<Button Command="{Binding Path=SubmitCommand}" />

Các bạn có thể xem thêm tại đây

Tương tác Triggers và Commands

Sau đây cho thấy cách sử dụng Blend EventTrigger được cấu hình để nghe sự kiện SelectionChanged của ListBox. Khi sự kiện này xảy ra, SelectedCommand được gọi ra bởi InvokeCommandAction.

namespace interactivity cho XAML:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<ListBox ItemsSource="{Binding Items}" SelectionMode="Single">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding SelectedCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

Bài viết Prism Library 5.0 for WPF – Implementing MVVM Pattern

https://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx#sec10

3 thoughts on “Prism Library 5.0 for WPF – Triển khai mô hình MVVM

  1. Pingback: Prism Library 5.0 for WPF – Khởi tạo ứng dụng | Phạm Duy Anh

  2. Pingback: Bài 2: Tạo một ứng dụng với MVVM đơn giản – Từng bước triển khai MVVM trong WPF | Phạm Duy Anh

  3. Pingback: Bài 2: Tạo một ứng dụng đơn giản với mô hình MVVM – Từng bước triển khai MVVM trong WPF | Phạm Duy Anh

Leave a Reply

Your email address will not be published.