Nội dung
Giới thiệu
Bạn cần bind một thuộc tính của các UI Elements đến một thuộc tính của CLR Object. Trong bài này, csharpcanban sẽ hướng dẫn các bạn thực hiện Bind data từ Texbox đến đối tượng Person như hình dưới đây:
Hướng dẫn Bind Data đến CLR Objects trong wpf
Vấn đề đặt ra: bạn cần bind một thuộc tính của các UI Elements đến một thuộc tính của CLR Object.
Giải pháp: Để sử CLR Object như là một binding source, bạn phải cho class của object đó implement interface System.ComponentModel.InotifyPropertyChanged.
Giải thích: Khi bạn bind một thuộc tính của 1 UI Element (chẳng hạn textbox) đến 1 thuộc tính của 1 object với Mode = Oneway hoặc Twoway, bạn phải cho class ojbect implement interface InotifyPropertyChanged, vì interface này thiết đặt thi công 1 event PropertyChanged để giúp bạn phát ra thông điệp thay đổi giá trị từng thuộc tính của object khi các giá trị trên thuộc tính của UI Element data-binding đến nó.
Xây dựng ứng dụng
Đầu tiên bạn thiết kế giao diện người dùng như sau:
<Window x:Class="Solution04.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Bind to CLR Objects" Height="300" Width="300"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="74"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="26"/> <RowDefinition Height="26"/> <RowDefinition Height="26"/> <RowDefinition Height="26"/> <RowDefinition Height="10"/> <RowDefinition Height="26"/> </Grid.RowDefinitions> <TextBlock Margin="4" Text="First Name" VerticalAlignment="Center"></TextBlock> <TextBox Margin="4" Grid.Column="1" Text="{Binding Path=FirstName, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}"></TextBox> <TextBlock Margin="4" Grid.Row="1" Text="Last Name" VerticalAlignment="Center"></TextBlock> <TextBox Margin="4" Grid.Row="1" Grid.Column="1" Text="{Binding Path=LastName, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}"></TextBox> <TextBlock Margin="4" Grid.Row="2" Text="Age" VerticalAlignment="Center"></TextBlock> <TextBox Margin="4" Grid.Row="2" Grid.Column="1" Text="{Binding Path=Age, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}"></TextBox> <TextBlock Margin="4" Grid.Row="3" Text="Occupation" VerticalAlignment="Center"></TextBlock> <ComboBox x:Name="cboOccupation" Width="150" IsEditable="False" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Path=Occupation, Mode=TwoWay}"> <ComboBoxItem>Student</ComboBoxItem> <ComboBoxItem>Skilled</ComboBoxItem> <ComboBoxItem>Professional</ComboBoxItem> </ComboBox> <TextBlock Margin="4" Grid.Row="5" Text="Description" VerticalAlignment="Center"></TextBlock> <TextBox Margin="4" Grid.Row="5" Grid.Column="1" Text="{Binding Path=Description, Mode=Oneway, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" FontStyle="Italic"></TextBox> </Grid> </Window>
Trong mã XAML trên, bạn đã thấy cú pháp data binding, nhưng vẫn chưa hiểu nó binding đến đối tượng nào, mặc dù bạn đã có thể hiểu là nó binding đến thuôc tính: FirstName, LastName, Age, Occupation ,Description của một đối tượng nào đó. Bây giờ, bạn bắt đầu tạo ra 1 class đối tượng Person:
using System.ComponentModel; namespace Solution04 { class Person : INotifyPropertyChanged { private string firstname; public string FirstName { get { return firstname; } set { firstname = value; OnPropertyChanged("FirstName"); OnPropertyChanged("Description"); } } private string lastname; public string LastName { get { return lastname; } set { lastname = value; OnPropertyChanged("LastName"); OnPropertyChanged("Description"); } } private int age; public int Age { get { return age; } set { age = value; OnPropertyChanged("Age"); OnPropertyChanged("Description"); } } private string occupation; public string Occupation { get { return occupation; } set { occupation = value; OnPropertyChanged("Occupation"); OnPropertyChanged("Description"); } } public string Description { get { return string.Format("{0} {1}, {2} {3}", firstname, lastname, age, occupation); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (this.PropertyChanged!=null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }
Do class Person implement interface INotifyPropertyChanged cho nên nó buộc phải thi công event sau: public event PropertyChangedEventHandler PropertyChanged; đây là event sẽ giúp bạn phát sinh ra thông điệp thay đổi giá trị của thuộc tính dựa trên đối số là tên của thuộc tính truyền vào. Để thuận tiện, tớ tạo 1 method giúp phát sinh thông điệp:
private void OnPropertyChanged(string propertyName) { if (this.PropertyChanged!=null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
Kế đến là lúc dùng đến nó, rất đơn giản, chẳng hạn để phát sinh thông điệp thay đổi dữ liệu trên thuộc tính FirstName:
public string FirstName { get { return firstname; } set { firstname = value; OnPropertyChanged("FirstName"); OnPropertyChanged("Description"); } }
Do Description là thuộc tính chỉ đọc (read-only) nên mình muốn khi thay đổi FirstName thì Description cũng thay đổi theo. Các thuộc tính còn lại (LastName,Age,…) các bạn hiểu theo nghĩa tương tự. Cuối cùng, trong phần code-behind Window1.xaml.cs, bạn thêm code như sau:
using System.Windows; namespace Solution04 { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); //thêm vào đoạn mã này this.DataContext = new Person() { FirstName = "Công", LastName = "Minh", Age = 22, Occupation = "Professional" }; } } }
Kết luận
Như vậy, trên đây csharpcanban.com đã Hướng dẫn các bạn xây dựng ứng dụng để Bind Data từ Textbox tới Object Person. Hãy vận dụng ngay bạn nhé. Chúc các bạn thành công.