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
Chủ Nhật, 4 tháng 1, 2015
Windows Presentation Foundation(WPF) cho phép các nhà phát triển có thể thay đổi hoàn toàn cái nhìn tổng quan và cách ứng xử của các Control. Điều này được thực hiện bằng cách sử dụng Control-Style và Control-Templates. Điều đó có nghĩa là bạn có một Button nhưng nó không chỉ đơn điệu là một hình chữ nhật mà có thể là một hình ảnh náo đó mà bạn muốn. Ở nội dung này tôi sẽ hướng dẫn các bạn tạo một Control-Templates cho TextBox.
Trước hết chúng ta cần phân biệt khái niệm Style và Tamplates
- Style: là cách thể hiện của một đối tượng về màu sắc, độ trong suốt.. và các thuộc tính ấy được phủ lên đối tượng - chúng có thể được ghi đè lên các thuộc tính mặc định nếu cần thiết, các Style có thể được áp dụng cho tất cả các Element cùng loại.
- Template: là cách thể hiện nội dung mang tính "cơ bắp" hơn, nó như một bộ khung được đặc lên trên bộ khung mặc định và không thay thế chúng, các Template chỉ được áp dụng cho các Control.
Một ví dụ cho sự khác biệt giữa Style và Tamplates: Style như một bộ đồ, nếu bộ đồ ấy dành cho con người dĩ nhiên phải có tay áo, cổ áo, ống quần... tất cả những thứ đó một người bình thường đều phải có, bộ đồ ấy được khoác lên người và chúng ta sẽ không thể thấy được phần tự nhiên trước đó, trong khi đó Template có thể là một bộ cánh, một chiếc giáp chiến đồ sộ hoặc cũng có thể là một cánh tay thứ ba... Và bộ cánh sẽ mang nhiều tính hành xử hơn một bộ đồ vì thế Styles áp dụng cho Element và Template chỉ áp dụng cho Control.
Các Style và Tamplates có thể được định nghĩa trong một thẻ con của đối tượng cần áp dụng(chỉ có tác dụng trong đối tượng đó)
- <TextBox.Style>[my style]</TextBox.Style>
- <TextBox.Template>[my template]</TextBox.Template>
hoặc được định nghĩa trong cặp thẻ Resources của thẻ root(phạm vi sử dụng trong thẻ root)
- <Window.Resources>[my style][my template]</Window.Resources>
- <Control.Resources>[my style][my template]</Control.Resources>
hay mở rộng phạm vi sử dụng lớn tối đa bằng cách định nghĩa chúng trong một file Resource riêng và đăng ký resource trong file App.xaml
Hôm nay tôi sẽ hướng dẫn các bạn cách tạo Style và Template cho TextBox, các bạn có thể xem các Template và Styles tôi đã làm sẵn dưới đậy.
Trước tiên chúng ta sẽ Add một file Resource bằng cách Add->New item và chọn Resource(WPF)
[code language="xml"]
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d">
<!-- Các resource được được định nghĩa dưới đây-->
<!-- Các resource được được định nghĩa bên trên-->
</ResourceDictionary>
[/code]
Quay lại file App.xaml, chúng ta hoàn thiện việc đăng ký resource như sau
[code language="xml"]
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.App"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!-- Resources scoped at the Application level should be defined here. -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Các tập tin resource được đăng ký bên dưới-->
<ResourceDictionary Source="ReDicTemplate.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
[/code]
I> Cách tạo một Style
Tôi thêm một thẻ <Style/> với nội dung hoàn thiện bên dưới, trong đó các property "Key, TargetType, BasedOn" nhất thiết phải có.
Mục đích của Style này là các TextBox áp dụng nó đều sẽ có nền màu xanh và chữ trắng, Padding = 5 và BorderThickness = 1, lượi ích là tôi sẽ tiết kiệm khá nhiều thời gian cho việc quy định các thuộc tính trên cho 1000 TextBox giống nhau.
[code language="xml"]
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d">
<!-- Các resource được được định nghĩa dưới đây-->
<!-- Một Style phải có x:Key-->
<Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="Green"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<!-- Có thể định nghĩa một Template như thế này-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Các resource được được định nghĩa bên trên-->
</ResourceDictionary>
[/code]
Key --> là mã nhận dạn cho một đối tượng trong ngôn ngữ XAML, được dùng khi muốn áp dụng style
BasedOn --> Chỉ ra một style parent bạn muốn kế thừa, tôi không kế thừa từ style nào cả
TargetType --> Chỉ ra một kiểu đối tượng có thể áp dụng style này, ở đây tôi dùng cho TextBox
Quay về Control chúng ta muốn áp dụng Style và set propery Style của control đó với giá trị là Key của Style trên.
[code language="xml"]
<TextBox Margin="10,10,10,0" Tag="My Name"
Text="Pham Tuan" VerticalAlignment="Top"
Style="{DynamicResource TextBoxStyle1}"/>
[/code]
Kết quả
Như vậy là xong phần Style, để có một style thật sự đẹp mắt chúng ta cần phải sử dụng nhiều kỹ thuật khác nhau Binding, Trigger, Storybroad ... tôi sẽ hướng dẫn ở một bài khác.
II> Cách tạo một Template
Template có hai dạng: Control Template và Data Template
- Control Template: Là cách thức hiển thị của một Control, tức vẽ bề ngoài của chính nó
- Data Template: Là cách hiển thị của phần dữ liệu mà nó chứa đựng, tức vẽ bề ngoài của các Item khi nó hiển thị trong lòng mình(Thường dùng với các control như ListBox, GridView, ComboBox...)
A> ControlTemplate
Tôi thêm một thẻ <ControlTemplate/> với nội dung hoàn thiện bên dưới, trong đó các property "Key, TargetType" nhất thiết phải có.
Mục đính tôi tạo một Template vì tôi muốn có một TextBox với phần Title hiển thị phía trước và phần nhập nội dung lền kề bên phải, phần cuối cùng bên phải TextBox có một Icon làm cảnh, màu nền phần Title trùng màu viền của TextBox(Nên tôi dùng TemplateBinding BorderBrush), nội dung Title được Binding đến thuộc tính Tag của TextBox(Nên tôi dùng TemplateBinding Tag)
[code language="xml"]
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d">
<!-- Các resource được được định nghĩa dưới đây-->
<!-- Phần Style ở trên sẽ ở đây-->
<!-- Một ControlTemplate phải có x:Key-->
<ControlTemplate x:Key="TextBoxBaseTemplate" TargetType="{x:Type TextBoxBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" MinWidth="100" Content="{TemplateBinding Tag}" Padding="4,1,4,2" VerticalContentAlignment="Center" Background="{TemplateBinding BorderBrush}" Foreground="White"/>
<ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Grid.ColumnSpan="1" Grid.Column="1" VerticalContentAlignment="Center" Padding="0,0,0,2"/>
<Label FontFamily="Webdings" Content="." VerticalContentAlignment="Center" Padding="5,0" Foreground="White" Margin="0" Grid.Column="3" Background="{TemplateBinding BorderBrush}"/>
</Grid>
</Border>
</ControlTemplate>
<!-- Các resource được được định nghĩa bên trên-->
</ResourceDictionary>
[/code]
Border --> kể từ thẻ này đến các thẻ con là phần chúng ta thiết kế
ScrollViewer --> là thẻ mặc định của TextBox chịu trách nhiệm hiển thị và nhận key nhập từ bản phím, tôi giữ nguyên như mặc định.
Chú ý --> Chúng ta sẽ bắc gặp một định dạng như sau Content="{TemplateBinding Tag}" ý nghĩa như sau: TemplateBinding là một kiểu DataBinding nhưng Binding đến các thuộc tính của một Control đã được chỉ ra tại thuộc tính TargetType.
Cũng như Style, chúng ta áp dụng template cho một control bằng cách gọi key của nó
[code language="xml"]
<TextBox Margin="10,10,10,0" TextWrapping="Wrap" Tag="My Name"
Text="Pham Tuan" VerticalAlignment="Top" BorderBrush="#FF007ACC"
Template="{DynamicResource TextBoxBaseTemplate}" Padding="0,2"/>
[/code]
Kết quả
B> DataTemplate
Tôi xin nhắc lại rằng, DataTemplate dùng để thể hiện cho một Item trong ItemSource của các control có khả năng chứa các list item như ComboBox, ListBox, GridView...
Ở ví dụ này tôi có một class Per chứa thông tin một người gồm Name, YearOld, Address, Title, nếu tôi dùng một ListBox đơn thuần - tôi sẽ hiển thị được duy nhất một nội dung tương ứng một property trong các property của đối tượng Per cho mỗi item của ListBox.
[code language="csharp"]
internal class Per
{
public string Title { set; get; }
public string Name { set; get; }
public int YearOld { set; get; }
public string Address { set; get; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
var list = new List<Per>()
{
new Per() {Name = "Phạm Tuân",Title = "Quán quân" ,Address = "Phước Long B, Q9", YearOld = 21},
new Per() {Name = "Phạm Văn Chu", Title = "Á quân",Address = "Phước Long A, Q9", YearOld = 22}
};
listBox.ItemsSource = list; //ListBox trên
listBox2.ItemsSource = list; //ListBox dưới
}
}
[/code]
[caption id="attachment_294" align="aligncenter" width="660"]
No-DataTemplate[/caption]Nhưng tôi muốn hiển thị trong ListBox nhiều thông tin hơn thế thì làm thế nào? Tôi tiến hành thiết kế DataTemplate, tôi add dataTemplate cho ListBox , với mỗi Item của ListBox sẽ chứa 3 TextBox hiển thị 3 nội dung khác nhau được Binding đến 3 thuộc tính của một Item như sau trong ListBox.ItemSource.
[code language="xml"]
<ListBox.ItemTemplate>
<DataTemplate>
<!-- Tiến hành thiết kế Start-->
<!--Thiết kế cho một Item của ListBox Start-->
<GroupBox Header="{Binding Title}"> <!--Binding đến thuộc tính Title-->
<StackPanel x:Name="panel" HorizontalAlignment="Stretch" >
<!--TextBox1 Binding đến thuộc tính Name-->
<TextBox Margin="2,2,2,0" Text="{Binding Name}"/>
<!--TextBox1 Binding đến thuộc tính YearOld-->
<TextBox Margin="2,2,2,0" Text="{Binding YearOld}" />
<!--TextBox1 Binding đến thuộc tính Address-->
<TextBox Margin="2,2,2,2" Text="{Binding Address}"/>
</StackPanel>
</GroupBox>
<!--Thiết kế cho một Item của ListBox End-->
<!-- Tiến hành thiết kế End-->
</DataTemplate>
</ListBox.ItemTemplate>
[/code]
Kết quả
Để cho đẹp hơn(theo cách cảu tôi), 3 TextBox kia tôi sẽ apply cho nó 3 ControlTemplate tôi đã thiết kế trước đó.
[code language="xml"]
<ListBox.ItemTemplate>
<DataTemplate>
<GroupBox Header="{Binding Title}">
<StackPanel x:Name="panel" HorizontalAlignment="Stretch" >
<TextBox Margin="2,2,2,0" TextWrapping="Wrap" Tag="Name" BorderThickness="0"
Text="{Binding Name}" VerticalAlignment="Top" VerticalContentAlignment="Center"
BorderBrush="Green" Template="{DynamicResource TextBoxBase2}"
Background="{x:Null}" Padding="0,2"/>
<TextBox Margin="2,2,2,0" TextWrapping="Wrap" Tag="Year-Old"
Text="{Binding YearOld}" VerticalAlignment="Top" VerticalContentAlignment="Center"
BorderBrush="#FF007ACC" Template="{DynamicResource TextBoxBaseTemplate}"
Background="{x:Null}" Padding="0,2"/>
<TextBox Margin="2,2,2,2" TextWrapping="Wrap" Tag="Address"
Text="{Binding Address}" VerticalAlignment="Top" VerticalContentAlignment="Center"
BorderBrush="#FF007ACC" Template="{DynamicResource TextBoxBaseTemplate}"
Background="{x:Null}" Padding="0,2"/>
</StackPanel>
</GroupBox>
</DataTemplate>
</ListBox.ItemTemplate>
[/code]
Kết quả là
Các bạn có thể tham khảo sourcecode, hãy đoán đọc các kỹ thuật tiếp theo để có một Template thật sự linh hoạt và thân thiện.
Chúc các bạn thành công!
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