Thuộc tính phụ thuộc là một loại thuộc tính cụ thể trong đó giá trị được theo sau bởi một hệ thống thuộc tính quan tâm cũng là một phần của Ứng dụng Windows Runtime. Một lớp xác định thuộc tính phụ thuộc phải được kế thừa từ lớp DependencyObject.
Nhiều lớp điều khiển giao diện người dùng được sử dụng trong XAML có nguồn gốc từ lớp DependencyObject và hỗ trợ các thuộc tính phụ thuộc. Mã XAML sau đây tạo một nút với một số thuộc tính.
<Window x:Class = "XAMLDependencyProperty.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:XAMLDependencyProperty"
Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<Button Height = "40" Width = "175" Margin = "10" Content = "Dependency Property">
<Button.Style>
<Style TargetType = "{x:Type Button}">
<Style.Triggers>
<Trigger Property = "IsMouseOver" Value = "True">
<Setter Property = "Foreground" Value = "Red" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
Phần mở rộng đánh dấu x: Type trong XAML có chức năng tương tự như typeof () trong C #. Nó được sử dụng khi các thuộc tính được chỉ định có kiểu đối tượng, chẳng hạn như <Style TargetType = “{x: Type Button}”>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra MainWindow sau. Khi chuột qua nút, nó sẽ thay đổi màu nền trước của nút. Khi con chuột rời khỏi nút, nó sẽ thay đổi trở lại màu ban đầu.
Sự khác biệt chính giữa các thuộc tính phụ thuộc và các thuộc tính CLR khác là:
- Thuộc tính CLR có thể đọc / ghi trực tiếp từ thành viên private của một lớp bằng cách sử dụng getter và setter . Trong trường hợp thuộc tính phụ thuộc, nó không được lưu trữ trong một đối tượng cục bộ.
- Thuộc tính phụ thuộc được lưu trữ trong từ điển các cặp khóa / giá trị được cung cấp bởi lớp DependencyObject.
- Nó cũng tiết kiệm rất nhiều bộ nhớ vì nó lưu trữ tài sản khi thay đổi.
- Nó cũng có thể bị ràng buộc trong XAML.
Trong khuôn khổ .NET, các thuộc tính phụ thuộc tùy chỉnh cũng có thể được xác định. Dưới đây là các bước để xác định thuộc tính phụ thuộc tùy chỉnh trong C #.
- Khai báo và đăng ký thuộc tính phụ thuộc của bạn với đăng ký cuộc gọi hệ thống.
- Cung cấp setter và getter cho tài sản.
- Xác định một trình xử lý tĩnh để xử lý bất kỳ thay đổi nào xảy ra trên toàn cầu.
- Xác định một trình xử lý cá thể để xử lý bất kỳ thay đổi nào xảy ra với cá thể cụ thể đó.
Dưới đây là mã trong C # cho thuộc tính phụ thuộc được xác định để đặt thuộc tính SetText của điều khiển người dùng.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication3 {
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
}
public static readonly DependencyProperty
SetTextProperty = DependencyProperty.Register("SetText", typeof(string),
typeof(UserControl1), new PropertyMetadata("",
new PropertyChangedCallback(OnSetTextChanged)));
public string SetText {
get {return(string) GetValue(SetTextProperty); }
set {SetValue(SetTextProperty, value);}
}
private static void OnSetTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
UserControl1 UserControl1Control = d as UserControl1;
UserControl1Control.OnSetTextChanged(e);
}
private void OnSetTextChanged(DependencyPropertyChangedEventArgs e) {
tbTest.Text = e.NewValue.ToString();
}
}
}
Đây là tệp XAML trong đó TextBlock được định nghĩa là điều khiển của người dùng và thuộc tính Text sẽ được gán cho nó bởi thuộc tính phụ thuộc SetText.
Mã XAML sau đây tạo điều khiển người dùng với việc khởi tạo thuộc tính phụ thuộc SetText của nó và một số thuộc tính khác.
<Window x:Class = "WpfApplication3.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views = "clr-namespace:WpfApplication3"
Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<views:UserControl1 SetText = "Hellow World" />
</Grid>
</Window>
Hãy chạy ứng dụng này và bạn có thể thấy ngay trong MainWindow của chúng tôi rằng thuộc tính phụ thuộc để kiểm soát người dùng đã được sử dụng thành công dưới dạng Văn bản.
XAML – Tài nguyên
Tài nguyên thường là các định nghĩa được kết nối với một số đối tượng mà bạn chỉ muốn sử dụng thường xuyên hơn một lần. Nó có khả năng lưu trữ dữ liệu cục bộ cho các điều khiển hoặc cho cửa sổ hiện tại hoặc toàn cầu cho toàn bộ ứng dụng.
Việc xác định một đối tượng làm tài nguyên cho phép chúng ta truy cập nó từ một nơi khác. Do đó, nó cho phép tái sử dụng. Tài nguyên được định nghĩa trong từ điển tài nguyên và bất kỳ đối tượng nào cũng có thể được định nghĩa là tài nguyên, biến nó thành tài sản có thể chia sẻ một cách hiệu quả. Một khóa duy nhất được chỉ định cho tài nguyên XAML và với khóa đó, nó có thể được tham chiếu bằng cách sử dụng tiện ích mở rộng đánh dấu StaticResource.
Hãy xem lại một ví dụ đơn giản trong đó hai khối văn bản được tạo với một số thuộc tính và màu nền trước của chúng được xác định trong Window.Resources .
<Window x:Class = "XAMLResources.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "MainWindow" Height = "350" Width = "604">
<Window.Resources>
<SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush>
</Window.Resources>
<StackPanel Orientation = "Vertical">
<TextBlock Foreground = "{StaticResource myBrush}"
Text = "First Name" Width = "100" Margin = "10" />
<TextBlock Foreground = "{StaticResource myBrush}"
Text = "Last Name" Width = "100" Margin = "10" />
</StackPanel>
</Window>
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra MainWindow sau. Bạn có thể thấy hai khối văn bản với màu nền trước là xanh lam. Ưu điểm của tài nguyên là nếu có nhiều khối văn bản và bạn muốn thay đổi màu nền của chúng, thì bạn chỉ cần thay đổi nó trong từ điển tài nguyên.
Phạm vi tài nguyên
Tài nguyên được định nghĩa trong từ điển tài nguyên, nhưng có rất nhiều nơi mà từ điển tài nguyên có thể được định nghĩa. Trong ví dụ trên, một từ điển tài nguyên được định nghĩa ở cấp Cửa sổ / trang. Trong từ điển nào một tài nguyên được định nghĩa ngay lập tức giới hạn phạm vi của tài nguyên đó. Vì vậy, phạm vi, tức là nơi bạn có thể sử dụng tài nguyên, phụ thuộc vào nơi bạn đã xác định nó.
- Xác định tài nguyên trong từ điển tài nguyên của một lưới và nó có thể truy cập được bởi lưới đó và chỉ bởi các phần tử con của nó.
- Xác định nó trên một cửa sổ / trang và nó có thể truy cập được bởi tất cả các phần tử trên cửa sổ / trang đó.
- Bạn có thể tìm thấy gốc ứng dụng trong từ điển tài nguyên App.xaml. Nó là gốc của ứng dụng của chúng tôi, vì vậy các tài nguyên được xác định ở đây được áp dụng cho toàn bộ ứng dụng.
Về phạm vi của tài nguyên, thông thường nhất là cấp ứng dụng, cấp trang và cấp phần tử cụ thể như Grid, StackPanel, v.v.
Từ điển tài nguyên
Từ điển tài nguyên trong ứng dụng XAML ngụ ý từ điển tài nguyên trong các tệp riêng biệt. Nó được theo sau trong hầu hết các ứng dụng XAML. Việc xác định tài nguyên trong các tệp riêng biệt có thể có những lợi ích sau:
- Tách biệt giữa việc xác định tài nguyên trong từ điển tài nguyên và mã liên quan đến giao diện người dùng.
- Việc xác định tất cả các tài nguyên trong một tệp riêng biệt, chẳng hạn như App.xaml sẽ làm cho chúng có sẵn trên Ứng dụng.
Vì vậy, làm thế nào chúng ta có thể xác định tài nguyên của mình trong từ điển tài nguyên trong một tệp riêng biệt? Nó rất dễ dàng, chỉ cần thêm một từ điển tài nguyên mới thông qua Visual Studio theo các bước sau:
- Trong giải pháp của bạn, hãy thêm một thư mục mới và đặt tên là ResourceDictionaries .
- Nhấp chuột phải vào thư mục này và chọn Resource Dictionary từ mục Add menu con và đặt tên là DictionaryWithBrush.xaml
Chúng ta hãy xem xét các ứng dụng tương tự; chỉ từ điển tài nguyên hiện được xác định ở cấp Ứng dụng.
Đây là mã XAML cho MainWindow.xaml.
<Window x:Class = "XAMLResources.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "MainWindow" Height = "350" Width = "604">
<StackPanel Orientation = "Vertical">
<TextBlock Foreground = "{StaticResource myBrush}" Text = "First Name"
Width = "100" Margin = "10" />
<TextBlock Foreground = "{StaticResource myBrush}" Text = "Last Name"
Width = "100" Margin = "10"/>
</StackPanel>
</Window>
Đây là cách triển khai trong DictionaryWithBrush.xaml –
<ResourceDictionary
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush>
</ResourceDictionary>
Đây là cách triển khai trong app.xaml –
<Application x:Class = "XAMLResources.App"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri = "MainWindow.xaml">
<Application.Resources>
<ResourceDictionary Source = " XAMLResources\ResourceDictionaries\DictionaryWithBrush.xaml" />
</Application.Resources>
</Application>
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra kết quả sau:
XAML – Mẫu
Mẫu mô tả giao diện tổng thể và hình thức trực quan của điều khiển. Đối với mỗi điều khiển, có một mẫu mặc định được liên kết với nó để tạo giao diện cho điều khiển đó.
Trong XAML, bạn có thể dễ dàng tạo các mẫu của riêng mình khi bạn muốn tùy chỉnh hành vi trực quan và hình thức trực quan của điều khiển. Kết nối giữa logic và mẫu có thể đạt được bằng cách liên kết dữ liệu.
Sự khác biệt chính giữa kiểu và mẫu là –
- Kiểu chỉ có thể thay đổi giao diện của điều khiển của bạn với các thuộc tính mặc định của điều khiển đó.
- Với các mẫu, bạn có thể truy cập nhiều phần của điều khiển hơn là trong các kiểu. Bạn cũng có thể chỉ định cả hành vi hiện có và hành vi mới của điều khiển.
Có hai loại mẫu được sử dụng phổ biến nhất.
- Mẫu điều khiển
- Mẫu dữ liệu
Mẫu điều khiển
Mẫu điều khiển xác định hoặc chỉ định hình thức và cấu trúc trực quan của điều khiển. Tất cả các phần tử giao diện người dùng đều có một số kiểu giao diện cũng như hành vi, ví dụ: Nút có giao diện và hành vi. Sự kiện nhấp chuột hoặc sự kiện di chuột là các hành vi được kích hoạt để phản ứng với một nhấp chuột và di chuột, đồng thời có một giao diện mặc định của nút có thể được thay đổi bởi Mẫu điều khiển.
Hãy xem lại một ví dụ đơn giản trong đó hai nút được tạo với một số thuộc tính. Một là với mẫu và một là với nút mặc định .
<Window x:Class = "TemplateDemo.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "MainWindow" Height = "350" Width = "604">
<Window.Resources>
<ControlTemplate x:Key = "ButtonTemplate" TargetType = "Button">
<Grid>
<Ellipse x:Name = "ButtonEllipse" Height = "100" Width = "150" >
<Ellipse.Fill>
<LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4">
<GradientStop Offset = "0" Color = "Red"/>
<GradientStop Offset = "1" Color = "Orange"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<ContentPresenter Content = "{TemplateBinding Content}"
HorizontalAlignment = "Center" VerticalAlignment = "Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property = "IsMouseOver" Value = "True">
<Setter TargetName = "ButtonEllipse" Property = "Fill" >
<Setter.Value>
<LinearGradientBrush StartPoint = "0,0.2" EndPoint="0.2,1.4">
<GradientStop Offset = "0" Color = "YellowGreen"/>
<GradientStop Offset = "1" Color = "Gold"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property = "IsPressed" Value = "True">
<Setter Property = "RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX = "0.8" ScaleY = "0.8" CenterX = "0" CenterY = "0" />
</Setter.Value>
</Setter>
<Setter Property = "RenderTransformOrigin" Value = "0.5,0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Button Content = "Round Button!" Template = "{StaticResource ButtonTemplate}"
Width = "150" Margin = "50" />
<Button Content = "Default Button!" Height = "40" Width = "150" Margin = "5" />
</StackPanel>
</Window>
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra MainWindow sau:
Khi bạn di chuột qua nút có mẫu tùy chỉnh, sau đó nó cũng thay đổi màu sắc như hình dưới đây
Mẫu dữ liệu
Mẫu Dữ liệu xác định và chỉ định hình thức cũng như cấu trúc của tập hợp dữ liệu. Nó cung cấp sự linh hoạt để định dạng và xác định cách trình bày dữ liệu trên bất kỳ phần tử giao diện người dùng nào. Nó chủ yếu được sử dụng trên các điều khiển Item liên quan đến dữ liệu như ComboBox, ListBox, v.v.
Hãy xem một ví dụ đơn giản về mẫu dữ liệu. Mã XAML sau đây tạo một hộp kết hợp với Mẫu dữ liệu và các khối văn bản.
<Window x:Class = "XAMLDataTemplate.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "MainWindow" Height = "350" Width = "604">
<Grid VerticalAlignment = "Top">
<ComboBox Name = "Presidents" ItemsSource = "{Binding}" Height = "30" Width = "400">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal" Margin = "2">
<TextBlock Text = "Name: " Width = "95" Background = "Aqua" Margin = "2" />
<TextBlock Text = "{Binding Name}" Width = "95" Background = "AliceBlue" Margin = "2" />
<TextBlock Text = "Title: " Width = "95" Background = "Aqua" Margin = "10,2,0,2" />
<TextBlock Text = "{Binding Title}" Width = "95" Background = "AliceBlue" Margin = "2" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</Window>
Đây là cách triển khai trong C #, trong đó đối tượng nhân viên được gán cho DataContext
using System;
using System.Windows;
using System.Windows.Controls;
namespace XAMLDataTemplate {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = Employee.GetEmployees();
}
}
}
Đây là cách triển khai trong C # cho lớp Nhân viên –
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace XAMLDataTemplate {
public class Employee : INotifyPropertyChanged {
private string name; public string Name {
get { return name; }
set { name = value; RaiseProperChanged(); }
}
private string title; public string Title {
get { return title; }
set { title = value; RaiseProperChanged(); }
}
public static Employee GetEmployee() {
var emp = new Employee() {
Name = "Waqas", Title = "Software Engineer" };
return emp;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaiseProperChanged( [CallerMemberName] string caller = ""){
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
public static ObservableCollection<Employee> GetEmployees() {
var employees = new ObservableCollection<Employee>();
employees.Add(new Employee() { Name = "Ali", Title = "Developer" });
employees.Add(new Employee() { Name = "Ahmed", Title = "Programmer" });
employees.Add(new Employee() { Name = "Amjad", Title = "Desiner" });
employees.Add(new Employee() { Name = "Waqas", Title = "Programmer" });
employees.Add(new Employee() { Name = "Bilal", Title = "Engineer" });
employees.Add(new Employee() { Name = "Waqar", Title = "Manager" });
return employees;
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra kết quả sau. Nó chứa một hộp kết hợp và khi bạn nhấp vào hộp kết hợp, bạn sẽ thấy rằng tập hợp dữ liệu được tạo trong lớp Nhân viên được liệt kê dưới dạng các mục hộp kết hợp.