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ứ Năm, 25 tháng 12, 2014
Bài viết này cho ta thấy làm thế nào để có thể sử dụng một ErrorTemplate và kích hoạt một Style để cung cấp thông tin phản hồi trực quan nhằm thông báo cho người dùng khi một giá trị không hợp lệ được nhập vào, dựa trên một quy tắc xác nhận nào đó.
Chúng ta sẽ làm một ví dụ như sau: Tôi có một lớp Persional chứa thông tin một người nào đó với hai thuộc tính là Name và YearOld, tôi sẽ Binding dữ liệu vào hai TextBox. Yêu cầu khi người dùng nhập tên và tuổi vào hai TextBox kia là tên không nhỏ hơn 2 kí tự hoặc rỗng, tuổi phải lớn hơn >= 18. Nếu nhập sai sẽ có ToolTip thông báo lỗi và chuyển màu TexBox.
Tôi tiến hành tạo Style cho TextBox với những yêu cầu sau:
- Có phần Header với dữ liệu được BinDing từ Tag ( là một property) của TextBox.
- Màu nền của Header trùng với màu viền của TextBox (mặc định là Blue)
- Trigger: Nếu sảy ra một Validation.HasError (=True) thì màu nền Header và viền TextBox chuyển sang Red và có sẽ có ToolTip thông báo lỗi cụ thể.
Tôi đặc style này vào phần Window.Resources như sau.
[code language="xml"]
<Window.Resources>
<SolidColorBrush x:Key="TextBox.Static.Border" Color="#FFABAdB3"/>
<SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
<SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>
<Style x:Key="TxtStyleValidation" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid MinWidth="100" x:Name="grdHeader" Background="{TemplateBinding BorderBrush}">
<Label x:Name="lbHeader" Content="{TemplateBinding Tag}" Padding="5,0,5,2" VerticalContentAlignment="Center" Foreground="White" ></Label>
</Grid>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Grid.Column="1" VerticalContentAlignment="Center" Padding="5,2,2,1"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
</Trigger>
<!-- Phần chính-->
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
<Setter Property="Background" TargetName="grdHeader" Value="Red"/>
<Setter Property="BorderBrush" TargetName="border" Value="Red"/>
</Trigger>
<!-- Phần chính-->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
[/code]
Và Phần thể hiện nội dung chính được thiết kế như sau:
[code language="xml"]
<Window x:Class="Validation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<!--Chèn phần style trên vào đây -->
<StackPanel x:Name="Stack" Margin="10">
<TextBox x:Name="txtName" Height="23" TextWrapping="Wrap"
Text="{Binding Name,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" Tag="My Name"
VerticalAlignment="Top" Padding="5,1,2,1" Style="{DynamicResource TxtStyleValidation}"
BorderBrush="#FF0630AE" Margin="0,3,0,0"/>
<TextBox x:Name="txtYear" Height="23" TextWrapping="Wrap"
Text="{Binding YearOld, UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" Tag="Year-Old"
VerticalAlignment="Top" Padding="5,1,2,1" Style="{DynamicResource TxtStyleValidation}"
BorderBrush="#FF0630AE" Margin="0,3,0,0"/>
</StackPanel>
</Window>
[/code]
Kết quả cho style
[caption id="" align="aligncenter" width="525"]
Chúng ta đến phần quan trọng nhất là khởi tạo lớp Persional
Chúng ta tạo lớp Persional và phải kế thừa từ hai interface sau IDataErrorInfo và INotifyPropertyChanged. Ta có hình hài lớp này như sau (Tham khảo INotifyPropertyChanged để hiểu hơn về method OnPropertyChanged)
[code language="csharp"]
class Personal : IDataErrorInfo,INotifyPropertyChanged
{
private string _name;
private int _yearold;
public int YearOld
{
set
{
if (value != _yearold)
{
_yearold = value;
}
}
get { return _yearold; }
}
public string Name
{
set
{
value = value.Trim();
if (value !=_name)
{
_name = value;
}
}
get { return _name; }
}
// IDataErrorInfo
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get { throw new NotImplementedException(); }
}
//INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property){}
}
[/code]
Hoàn thành lớp Persional như sau
[code language="csharp"]
class Personal:IDataErrorInfo,INotifyPropertyChanged
{
private string _name;
private int _yearold;
public int YearOld
{
set
{
if (value != _yearold)
{
_yearold = value;
OnPropertyChanged("YearOld");
}
}
get { return _yearold; }
}
public string Name
{
set
{
value = value.Trim();
if (value !=_name)
{
_name = value;
OnPropertyChanged("Name");
}
}
get { return _name; }
}
//IDataErrorInfo
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
string result = String.Empty;
switch (columnName)
{
case "Name":
if (String.IsNullOrEmpty(Name) || Name.Length < 2)
{
result = "Lỗi nhập liệu: tên không chính xác";
}
break;
case "YearOld":
if (YearOld < 18)
{
result = "Lỗi nhập liệu: Tuổi quá nhỏ";
}
break;
}
return result;
}
}
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this,new PropertyChangedEventArgs(property));
}
}
}
[/code]
Hoàn thành phần View và ViewModel xong ta tiến hành một bước đơn giản sau trước khi chạy thử ứng dụng
[code language="csharp"]
public MainWindow()
{
InitializeComponent();
Stack.DataContext = new Personal() { Name = "Phạm Tuân", YearOld = 21 };
}
[/code]
Kết quả như sau
[caption id="" align="aligncenter" width="525"]
Các bạn có thể tham khảo SourceCode tại đây, Phần tiếp theo nói về ValidationRule.
Chúc các bạn thành công!
Tuân Phạm
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
-
▼
2014
(18)
-
▼
tháng 12
(18)
- WPF - Các Vấn Đề Về Multi-Thread Trong WPF (Đa Luồng)
- Modern UI For WPF Thiết Kế Giao diện Modern Win8 V...
- WPF - Thiết Kế Giao Diện METRO Win8 Với Thư Viện M...
- WPF - Validation ValidationRule và Vấn Đề Về Thông...
- WPF - Validation ValidationRule và Vấn Đề Về Thông...
- Parallel Class Trong C# và Vấn Đề Xử lý Song Song
- Tìm Hiểu Về Delegate Trong C# và Cách Truyền Dữ Li...
- Extension Methods - Thêm Một Phương Thức Ngoài Vào...
- Indexer trong C# - Kỹ Thuật Duyệt Qua Phần Tử Tron...
- SourceCode - DataBinding và ValueConverter
- WPF - DataBinding và chuyển đổi kiểu dữ liệu IValu...
- SourceCode - DataBinding và UpdateSourceTrigger
- WPF - DataBinding và cở chế tự động update dữ liệu
- SourceCode - DataBinding
- WPF – Cơ Bản về Data Binding
- WPF - Bộ Công Cụ Đắc Lực Cho Thiết Kế Expression S...
- WPF - Các Thành Phần Của WPF
- WPF - Tổng quan về Windows Presentation Foundation
-
▼
tháng 12
(18)
0 nhận xét:
Đăng nhận xét