Blog chia sẽ kinh nghiệm lập trình và Technical VN. Nơi mà các bạn có thể học tập và tham khảo về những công nghệ mới nhất hiện nay về .NET
Thứ Bảy, 31 tháng 1, 2015
Khi các bạn làm một dự án khá lớn, nhu cầu tạo ra các Custom Control là không tránh khỏi, trong WinForm hay WPF đều cho phép chúng ta tạo ra các User-Control(userCtrl) với mục đích trên; Nói về khía cạnh WPF, để tạo ra một user-control có tính thuận tiện và linh hoạt cao chúng ta cần áp dụng nhiều kỹ thuật trong thiết kế cũng như lập trình - hôm nay chúng ta sẽ nói về một điều trong nhiều điều phải nắm nếu có ý định tạo một Control mang phong cách cá nhân.
Trong ví dụ sau đây tôi có một user-Control, userCtrl này chứa một TextBox, một Button và một Lable.
Trong XAML tôi thiết kế như sau
[code language="xml"]
<UserControl x:Name="userControl" x:Class="Dependency_property.userControls.MyuserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Background="#FF3399FF">
<Label Content="Header" VerticalContentAlignment="Center" Padding="5,1" Foreground="White"/>
</Grid>
<TextBox Grid.Column="1" VerticalContentAlignment="Center" Padding="5,1"/>
<Button x:Name="btnAction"Grid.Column="2"/>
</Grid>
</UserControl>
[/code]
Vấn đề phát sinh khi tôi dùng userCtrl này, tôi không thể nào thay đổi được nội dung của Button và cũng như không thể Get giá trị từ TextBox bởi vì các control này đã được che phủ bởi userCtrl nên tôi không thể nào truy cập được đến các thuộc tính của các control trong nó; giải quyết vấn đề này bằng Code-behind thì khá đơn giản nhưng chúng ta lại đang làm việc với WPF - XAML và vấn đề trực quan trong design là quan trọng.
[code language="xml"]
<StackPanel>
<!-- Làm sao để set Content cho Button bên trong userCtrl đây -->
<!-- Làm gì thấy được Button mà set trực tiếp -->
<local:MyuserControl x:Name="txtAdv"/>
</StackPanel>
[/code]
Cách giải quyết tôi đề cập ở trên cho code-behind là chúng ta tạo một số property của userCtrl làm cầu nối để set hoặc get value của các control bên trong - giống như cách nhìn nhận trong bài viết Create intance ; xong cách làm này có một số nhược điểm và Microsoft không khuyến cáo dùng(Cứ thử làm với các project lớn đi rồi sẽ gặp một vài vấn đề... hihi); Vì thế chúng ta dùng Dependency Property, ưu điểm là Dependency Property sẽ hỗ trợ nhiều khía cạnh hơn trong WPF(Style, Template, kế thừa property, hình ảnh động, 3D...) Cách dùng Dependency Property như sau:
1> Đăng ký Dependency Property
Trong code behind của userCtrl chúng ta tạo một Dependency Property
[code language="csharp"]
// Cho button
public static readonly DependencyProperty
ButtonContentproperty = DependencyProperty.Register(
"ButtonContent", typeof (object), typeof (MyuserControl),
new UIPropertyMetadata("Action"));
// Cho textBox
public static readonly DependencyProperty
TextBoxTextproperty = DependencyProperty.Register(
"TextBoxText", typeof (string), typeof (MyuserControl),
new UIPropertyMetadata("No text", OnValueChanged));
// Sự khác biệt khi textBox có thêm method "OnValueChanged"
// Vì tôi muốn làm một vài điều khi nội dung textBox bị changed
[/code]
Lưu ý:
- "ButtonContentproperty" là tên của DependencyProperty, property này sẽ được đăng ký với Type là object vì Content của Button là một object, Type của userCtrl sẽ sử dụng được nó là MyuserControl, và giá trị mặc định là một chuổi "Action".
- ButtonContentproperty này sẽ không thật sự dùng để chúng ta làm việc với XAML đâu nhé, trong XAML chúng ta truy xuất đến DependencyProperty với tên "ButtonContent" - lưu ý tên này(*)
2> Tạo một property thông thường
Tiếp theo tạo lần lược các property với kiểu trùng kiểu của DependencyProperty tương ứng, tên là tên tương ứng (ví dụ "ButtonContent" trùng với (*))
[code language="csharp"]
// Cho button
public object ButtonContent
{
// Property này sẽ truy xuất đến DependencyProperty trên kia
get { return GetValue(ButtonContentproperty); }
set { SetValue(ButtonContentproperty, value); }
}
// Cho textBox
public string TextBoxText
{
// Property này sẽ truy xuất đến DependencyProperty trên kia
get { return (string) GetValue(TextBoxTextproperty); }
set { SetValue(TextBoxTextproperty, value); }
}
[/code]
3> Làm việc với Event
Tới đây chúng ta đã xong phần DependencyProperty, để hoàn chỉnh userCtrl này chúng ta cần xử lý việc Click button, đơn giản là tại code-behind của userCtrl ta public một event "ButtonClick" kiểu RoutedEventHandler để bên ngoài có thể tiếp cận; tại XAML của userCtrl, sự kiện Click của Button được chỉ định đến một Method "ActionExecuting" trong code-behind của userCtrl - tại đây chúng ta kiểm tra và thực thi event "ButtonClick"
[code language="csharp"]
// Nơi dùng userCtrl sẽ đăng ký event này
public event RoutedEventHandler ButtonClick;
// Khi Button.Click sảy ra, hàm dưới đây sẽ được gọi để thực thi các đăng ký event
private void ActionExecuting(object sender, RoutedEventArgs e)
{
if (ButtonClick != null)
{
ButtonClick.Invoke(this, new RoutedEventArgs());
}
}
[/code]
XAML của userCtrl
[code language="xml"]
<!-- nội dung khác -->
<Button x:Name="btnAction" Grid.Column="2" Margin="2,0,0,0"
Content="{Binding ButtonContent, ElementName=userControl,
UpdateSourceTrigger=PropertyChanged}"
Click="ActionExecuting"/>
<!-- nội dung khác -->
[/code]
Lưu ý: cách xử lý này vẫn cùi mía, cách rồ hơn đề cập sau
4> Cách dùng
Hãy xem về Binding nếu bạn chưa biết nhé, sau đây tôi binding Content/Text của các control đến property của userCtrl(là property chứ không phải DependencyProperty nha)
[code language="xml"]
<UserControl x:Name="userControl" x:Class="Dependency_property.userControls.MyuserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid Background="#FF3399FF">
<Label Content="Header" VerticalContentAlignment="Center" Padding="5,1" Foreground="White"/>
</Grid>
<TextBox Text="{Binding TextBoxText, ElementName=userControl, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1"
VerticalContentAlignment="Center" Padding="5,1"/>
<Button x:Name="btnAction"
Content="{Binding ButtonContent, ElementName=userControl, UpdateSourceTrigger=PropertyChanged}"
Click="ActionExecuting" Grid.Column="2"/>
</Grid>
</UserControl>
<!-- trong nội dung binding, ElementName=userControl là chỉ userCtrl cha -->
[/code]
Gọi dùng user-Control ở MainWindow
[code language="xml"]
<Window x:Class="Dependency_property.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:Dependency_property.userControls"
Title="MainWindow" Height="200" Width="525">
<Grid>
<local:MyuserControl x:Name="txtAdv" VerticalAlignment="Center" Margin="10,0" Height="30"
ButtonClick="TxtAdv_OnButtonClick"
TextBoxText="Hello world! this is user-control"
ButtonContent="Show" />
</Grid>
</Window>
[/code]
Kết quả
Chúc các bạn thành công! source code
Phạm Tuân
Search
Popular Posts
-
Phong cách thiết kế Material Design nhắm đến những đường nét đơn giản, sử dụng nhiều mảng màu đậm nổi bật, các đối tượng đồ họa trong giao ...
-
Hôm nay tôi sẽ giới thiệu với các bạn một Framework đến từ Microsoft - framework này không quá lớn nhưng là khá mạnh khi các bạn làm việc vớ...
-
WPF vượt trội hơn Winform về khoản Drawing , trong đó đặc biệt WPF hỗ trợ đồ họa rất tốt vì nó tương tác trực tiếp đến GPU. Hôm nay chúng t...
-
Hôm nay chúng ta sẽ tìm hiểu cách tạo ra các menu chuột phải trên ứng dụng WPF của mình. Ở bài này chúng ta xoay quanh việc tìm hiểu cách tạ...
-
Để dễ hiểu, các bạn hãy hình dung rằng: cùng một tập tin thực thi *.EXE nhưng bạn DoubleClick 10 lần cách quãng vào nó thì chuyện gì sẽ sảy ...
-
Trong bài viết trước tôi có giới thiệu về Extension Methods trong nguôn ngữ lập trình C#; hôm nay tôi sẽ nói về một vấn đề có ý nghĩa tương...
-
Hôm nay chúng ta sẽ thử đo xem thời gian query Data của "Foreach vs LinQ vs LinQasParallel" như thế nào. Tôi tạo một tool nhỏ để l...
-
Data Binding là kĩ thuật dùng để tạo gắn kết giữa phần giao diện ( UI ) và dữ liệu thông qua phần business logic hoặc giữa các đối tượng UI...
-
LOG4NET là một thư viện mã nguồn mở cho phép chúng ta tạo ra một hoặc nhiều tập tin log, kiểu log cũng như nội dung log một cách linh hoạt v...
-
Sau hai bài giới thiệu về Caliburn.Micro framework, hôm nay chúng ta sẽ cùng bắt tay vào làm một dự án nhỏ - HelloWorld. Step 1: Add referen...
Recent Posts
Blog Archive
-
▼
2015
(48)
-
▼
tháng 1
(18)
- WPF Study - Dependency Property
- WPF Study - How To Create Instance Of Class In XAML?
- WPF - TEXTBOX STYLE (INSPIRED BY ANDROID)
- WPF - RADIOBUTTON STYLE (INSPIRED BY ANDROID)
- WPF - TABCONTROL STYLE (INSPIRED BY ANDROID)
- WPF - SLIDER STYLE (INSPIRED BY ANDROID)
- WPF - CHECKBOX STYLE (INSPIRED BY ANDROID)
- WPF - TOGGLEBUTTON STYLE (INSPIRED BY ANDROID)
- WPF - Android UI Cho Giao Diện WPF
- ReSharper - Một Công Cụ Hỗ Trợ Đắc Lực Cho Dev
- Công Cụ Design UML Miễn Phí Tốt Nhất
- C# - Lắng Nghe Các Thông Báo Thay Đổi Của Hệ Thống...
- WPF - Cách Làm Hoạt Họa Trong WPF (Storyboard/Anim...
- Cách Tạo Một Ứng Dụng SingleInstance (Application)
- C# - Xây Dựng Ứng Dụng Đơn Giản Với Hook
- WPF - Tìm Hiểu Về Trigger Trong WPF, Một Vấn Đề Qu...
- WPF - Tìm Hiểu Về Control Styles Và Templates Tron...
- Log4net trong C# Và Tầm Quan Trọng Của Việc Tạo Lo...
-
▼
tháng 1
(18)
0 nhận xét:
Đăng nhận xét