WPF - Hướng dẫn nhanh
WPF là viết tắt của Windows Presentation Foundation. Nó là một khuôn khổ mạnh mẽ để xây dựng các ứng dụng Windows. Hướng dẫn này giải thích các tính năng mà bạn cần hiểu để xây dựng ứng dụng WPF và cách nó mang lại thay đổi cơ bản trong các ứng dụng Windows.
WPF lần đầu tiên được giới thiệu trong phiên bản .NET framework 3.0, sau đó rất nhiều tính năng khác đã được thêm vào trong các phiên bản .NET framework tiếp theo.
Kiến trúc WPF
Trước WPF, các khung giao diện người dùng khác do Microsoft cung cấp như các biểu mẫu MFC và Windows, chỉ là các trình bao bọc xung quanh các DLL của User32 và GDI32, nhưng WPF chỉ sử dụng rất ít User32. Vì thế,
- WPF không chỉ là một trình bao bọc.
- Nó là một phần của .NET framework.
- Nó chứa một hỗn hợp mã được quản lý và không được quản lý.
Các thành phần chính của kiến trúc WPF được thể hiện trong hình bên dưới. Phần mã quan trọng nhất của WPF là:
- Khung trình bày
- Bản trình bày cốt lõi
- Milcore
Các presentation framework và presentation core đã được viết bằng mã được quản lý. Milcore là một phần của mã không được quản lý cho phép tích hợp chặt chẽ với DirectX (chịu trách nhiệm hiển thị và kết xuất). CLR làm cho quá trình phát triển hiệu quả hơn bằng cách cung cấp nhiều tính năng như quản lý bộ nhớ, xử lý lỗi, v.v.
WPF - Ưu điểm
Trong các khung GUI trước đó, không có sự phân tách thực sự giữa cách một ứng dụng trông như thế nào và cách nó hoạt động. Cả GUI và hành vi đều được tạo bằng cùng một ngôn ngữ, ví dụ như C # hoặc VB.Net sẽ yêu cầu nhà phát triển nỗ lực nhiều hơn để triển khai cả giao diện người dùng và hành vi liên quan đến nó.
Trong WPF, các phần tử giao diện người dùng được thiết kế trong XAML trong khi các hành vi có thể được thực hiện bằng các ngôn ngữ thủ tục như C # và VB.Net. Vì vậy, rất dễ dàng để tách hành vi khỏi mã của nhà thiết kế.
Với XAML, các lập trình viên có thể làm việc song song với các nhà thiết kế. Sự tách biệt giữa GUI và hành vi của nó có thể cho phép chúng ta dễ dàng thay đổi giao diện của điều khiển bằng cách sử dụng các kiểu và mẫu.
WPF - Tính năng
WPF là một khuôn khổ mạnh mẽ để tạo ứng dụng Windows. Nó hỗ trợ nhiều tính năng tuyệt vời, một số trong số đó đã được liệt kê bên dưới -
Đặc tính | Sự miêu tả |
---|---|
Kiểm soát bên trong Kiểm soát | Cho phép xác định một điều khiển bên trong một điều khiển khác dưới dạng nội dung. |
Liên kết dữ liệu | Cơ chế hiển thị và tương tác dữ liệu giữa các phần tử UI và đối tượng dữ liệu trên giao diện người dùng. |
Dịch vụ truyền thông | Cung cấp một hệ thống tích hợp để xây dựng giao diện người dùng với các yếu tố phương tiện thông thường như hình ảnh, âm thanh và video. |
Mẫu | Trong WPF, bạn có thể xác định giao diện của một phần tử trực tiếp bằng Mẫu |
Ảnh động | Xây dựng tương tác và chuyển động trên Giao diện người dùng |
Đầu vào thay thế | Hỗ trợ nhập liệu đa chạm trên Windows 7 trở lên. |
Direct3D | Cho phép hiển thị đồ họa phức tạp hơn và các chủ đề tùy chỉnh |
Microsoft cung cấp hai công cụ quan trọng để phát triển ứng dụng WPF.
- Visual Studio
- Hỗn hợp biểu hiện
Cả hai công cụ đều có thể tạo các dự án WPF, nhưng thực tế là Visual Studio được các nhà phát triển sử dụng nhiều hơn, trong khi Blend được các nhà thiết kế sử dụng thường xuyên hơn. Đối với hướng dẫn này, chúng tôi chủ yếu sẽ sử dụng Visual Studio.
Cài đặt
Microsoft cung cấp phiên bản Visual Studio miễn phí có thể tải xuống từ VisualStudio .
Tải xuống các tệp và làm theo các bước dưới đây để thiết lập môi trường phát triển ứng dụng WPF trên hệ thống của bạn.
Sau khi tải xuống hoàn tất, hãy chạy installer. Hộp thoại sau sẽ được hiển thị.
Nhấn vào Install và nó sẽ bắt đầu quá trình cài đặt.
Khi quá trình cài đặt hoàn tất thành công, bạn sẽ thấy hộp thoại sau.
Đóng hộp thoại này và khởi động lại máy tính của bạn nếu được yêu cầu.
Bây giờ, hãy mở Visual Studio từ Menu Bắt đầu, hộp thoại sau sẽ mở ra.
- Sau khi tất cả hoàn tất, bạn sẽ thấy cửa sổ chính của Visual Studio.
Bây giờ bạn đã sẵn sàng để xây dựng ứng dụng WPF đầu tiên của mình.
Trong chương này, chúng tôi sẽ phát triển một ứng dụng Hello World WPF đơn giản. Vì vậy, chúng ta hãy bắt đầu thực hiện đơn giản bằng cách làm theo các bước dưới đây.
- Bấm vào tùy chọn menu Tệp> Mới> Dự án.
- Hộp thoại sau sẽ được hiển thị.
Trong Mẫu, chọn Visual C # và trong bảng điều khiển ở giữa, chọn Ứng dụng WPF.
Đặt tên cho dự án. KiểuHelloWorld trong trường tên và nhấp vào nút OK.
Theo mặc định, hai tệp được tạo, một tệp là XAML tệp (mainwindow.xaml) và tệp còn lại là CS tệp (mainwindow.cs)
Trên mainwindow.xaml, bạn sẽ thấy hai cửa sổ phụ, một cửa sổ là design window và cái kia là source (XAML) window.
Trong ứng dụng WPF, có hai cách để thiết kế giao diện người dùng cho ứng dụng của bạn. Một là chỉ cần kéo và thả các phần tử giao diện người dùng từ hộp công cụ vào Cửa sổ thiết kế. Cách thứ hai là thiết kế giao diện người dùng của bạn bằng cách viết thẻ XAML cho các phần tử giao diện người dùng. Visual Studio xử lý các thẻ XAML khi tính năng kéo và thả được sử dụng để thiết kế giao diện người dùng.
Trong tệp mainwindow.xaml, các thẻ XAML sau được viết theo mặc định.
<Window x:Class = "HelloWorld.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>
</Grid>
</Window>
- Theo mặc định, Grid được đặt làm phần tử đầu tiên sau trang.
- Hãy vào hộp công cụ và kéo một TextBlock vào cửa sổ thiết kế.
- Bạn sẽ thấy TextBlock trên cửa sổ thiết kế.
Khi bạn nhìn vào cửa sổ nguồn, bạn sẽ thấy rằng Visual Studio đã tạo mã XAML của TextBlock cho bạn.
Hãy thay đổi thuộc tính Text của TextBlock trong mã XAML từ TextBlock thành Hello World.
<Window x:Class = "HelloWorld.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>
<TextBlock x:Name = "textBlock" HorizontalAlignment = "Left"
Margin = "235,143,0,0" TextWrapping = "Wrap" Text = "Hello World!"
VerticalAlignment = "Top" Height = "44" Width = "102" />
</Grid>
</Window>
- Bây giờ, bạn cũng sẽ thấy sự thay đổi trên Cửa sổ thiết kế.
Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ thấy cửa sổ sau.
Xin chúc mừng! Bạn đã thiết kế và tạo ứng dụng WPF đầu tiên của mình.
Một trong những điều đầu tiên bạn sẽ gặp khi làm việc với WPF là XAML. XAML là viết tắt của Ngôn ngữ đánh dấu ứng dụng có thể mở rộng. Đó là một ngôn ngữ khai báo và đơn giản dựa trên XML.
Trong XAML, rất dễ dàng để tạo, khởi tạo và thiết lập các thuộc tính của các đối tượng có quan hệ phân cấp.
Nó chủ yếu được sử dụng để thiết kế GUI, tuy nhiên nó cũng có thể được sử dụng cho các mục đích khác, ví dụ, để khai báo quy trình làm việc trong Workflow Foundation.
Cú pháp cơ bản
Khi bạn tạo dự án WPF mới của mình, bạn sẽ gặp một số mã XAML theo mặc định trong MainWindow.xaml như hình dưới đây.
<Window x:Class = "Resources.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">
<Grid>
</Grid>
</Window>
Tệp XAML ở trên chứa các loại thông tin khác nhau. Bảng sau giải thích ngắn gọn vai trò của từng thông tin.
Thông tin | Sự miêu tả |
---|---|
<Cửa sổ | Nó là phần tử đối tượng mở hoặc vùng chứa của gốc. |
x: Class = "Resources.MainWindow" | Nó là một khai báo lớp một phần kết nối đánh dấu với mã lớp một phần được định nghĩa phía sau. |
xmlns = "http://schemas.microsoft.com/win fx / 2006 / xaml / Presentation" | Lập bản đồ không gian tên XAML mặc định cho ứng dụng / khuôn khổ WPF |
xmlns: x = "http://schemas.microsoft.com/w infx / 2006 / xaml" | Không gian tên XAML cho ngôn ngữ XAML ánh xạ nó tới tiền tố x: |
> | Phần tử cuối đối tượng của gốc |
<Lưới> </Grid> |
Nó đang bắt đầu và đóng các thẻ của một đối tượng lưới trống. |
</Window> | Đóng phần tử đối tượng |
Các quy tắc cú pháp cho XAML gần như tương tự như XML. Nếu bạn xem một tài liệu XAML, thì bạn sẽ nhận thấy rằng nó thực sự là một tệp XML hợp lệ, nhưng một tệp XML không nhất thiết phải là một tệp XAML. Đó là bởi vì trong XML, giá trị của các thuộc tính phải là một chuỗi trong khi trong XAML, nó có thể là một đối tượng khác được gọi là cú pháp phần tử Thuộc tính.
Cú pháp của một phần tử Object bắt đầu bằng một dấu ngoặc nhọn bên trái (<) theo sau là tên của một đối tượng, ví dụ như Button.
Xác định một số Thuộc tính và thuộc tính của phần tử đối tượng đó.
Phần tử Đối tượng phải được đóng bằng dấu gạch chéo (/) theo sau ngay sau dấu ngoặc vuông (>).
Ví dụ về đối tượng đơn giản không có phần tử con
<Button/>
Ví dụ về phần tử đối tượng với một số thuộc tính
<Button Content = "Click Me" Height = "30" Width = "60" />
Ví dụ về cú pháp thay thế xác định thuộc tính (Cú pháp phần tử thuộc tính)
<Button>
<Button.Content>Click Me</Button.Content>
<Button.Height>30</Button.Height>
<Button.Width>60</Button.Width>
</Button>
Ví dụ về đối tượng có phần tử con: StackPanel chứa Textblock làm phần tử con
<StackPanel Orientation = "Horizontal">
<TextBlock Text = "Hello"/>
</StackPanel>
Tại sao XAML trong WPF
XAML không chỉ là tính năng được biết đến rộng rãi nhất của WPF mà còn là một trong những tính năng bị hiểu nhầm nhiều nhất. Nếu bạn đã tiếp xúc với WPF, thì bạn chắc hẳn đã nghe nói về XAML; nhưng hãy lưu ý hai sự thật ít được biết đến sau đây về XAML -
- WPF không cần XAML
- XAML không cần WPF
Trên thực tế, chúng là những phần công nghệ có thể tách rời. Để hiểu điều đó có thể xảy ra như thế nào, hãy xem một ví dụ đơn giản trong đó một nút được tạo với một số thuộc tính trong XAML.
<Window x:Class = "WPFXAMLOverview.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>
<Button x:Name = "button" Content = "Click Me" HorizontalAlignment = "Left"
Margin = "150" VerticalAlignment = "Top" Width = "75" />
</StackPanel>
</Window>
Trong trường hợp bạn chọn không sử dụng XAML trong WPF, thì bạn cũng có thể đạt được kết quả GUI tương tự với ngôn ngữ thủ tục. Hãy xem cùng một ví dụ, nhưng lần này, chúng ta sẽ tạo một nút trong C #.
using System.Windows;
using System.Windows.Controls;
namespace WPFXAMLOverview {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
// Create the StackPanel
StackPanel stackPanel = new StackPanel();
this.Content = stackPanel;
// Create the Button
Button button = new Button();
button.Content = "Click Me";
button.HorizontalAlignment = HorizontalAlignment.Left;
button.Margin = new Thickness(150);
button.VerticalAlignment = VerticalAlignment.Top;
button.Width = 75;
stackPanel.Children.Add(button);
}
}
}
Khi bạn biên dịch và thực thi mã XAML hoặc mã C #, bạn sẽ thấy kết quả giống như hình dưới đây.
Từ ví dụ trên, rõ ràng là những gì bạn có thể làm trong XAML để tạo, khởi tạo và thiết lập thuộc tính của các đối tượng, các tác vụ tương tự cũng có thể được thực hiện bằng cách sử dụng mã.
XAML chỉ là một cách đơn giản và dễ dàng khác để thiết kế các phần tử giao diện người dùng.
Với XAML, không có nghĩa là những gì bạn có thể làm để thiết kế các phần tử giao diện người dùng là cách duy nhất. Bạn có thể khai báo các đối tượng trong XAML hoặc xác định chúng bằng mã.
XAML là tùy chọn, nhưng mặc dù vậy, nó là trọng tâm của thiết kế WPF.
Mục tiêu của XAML là cho phép các nhà thiết kế trực quan tạo ra các phần tử giao diện người dùng trực tiếp.
WPF nhằm mục đích làm cho nó có thể kiểm soát tất cả các khía cạnh trực quan của giao diện người dùng từ khi đánh dấu.
Có nhiều công nghệ mà các phần tử và thành phần được sắp xếp theo cấu trúc cây để người lập trình có thể dễ dàng xử lý đối tượng và thay đổi hành vi của một ứng dụng. Windows Presentation Foundation (WPF) có cấu trúc cây toàn diện dưới dạng các đối tượng. Trong WPF, có hai cách mà một cây đối tượng hoàn chỉnh được khái niệm hóa:
- Cấu trúc cây lôgic
- Cấu trúc cây trực quan
Với sự trợ giúp của các cấu trúc cây này, bạn có thể dễ dàng tạo và xác định mối quan hệ giữa các phần tử UI. Hầu hết, các nhà phát triển và nhà thiết kế WPF sử dụng ngôn ngữ thủ tục để tạo ứng dụng hoặc thiết kế phần giao diện người dùng của ứng dụng trong XAML, lưu ý đến cấu trúc cây đối tượng.
Cấu trúc cây lôgic
Trong các ứng dụng WPF, cấu trúc của các phần tử giao diện người dùng trong XAML thể hiện cấu trúc cây logic. Trong XAML, các yếu tố cơ bản của UI được nhà phát triển khai báo. Cây logic trong WPF định nghĩa như sau:
- Thuộc tính phụ thuộc
- Tài nguyên tĩnh và động
- Ràng buộc các yếu tố trên tên của nó, v.v.
Hãy xem ví dụ sau, trong đó một nút và một hộp danh sách được tạo.
<Window x:Class = "WPFElementsTree.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>
<Button x:Name = "button" Height = "30" Width = "70" Content = "OK" Margin = "20" />
<ListBox x:Name = "listBox" Height = "100" Width = "100" Margin = "20">
<ListBoxItem Content = "Item 1" />
<ListBoxItem Content = "Item 2" />
<ListBoxItem Content = "Item 3" />
</ListBox>
</StackPanel>
</Window>
Nếu bạn nhìn vào mã XAML, bạn sẽ quan sát một cấu trúc cây, tức là nút gốc là Window và bên trong nút gốc, chỉ có một nút con, đó là StackPanel. Nhưng StackPanel chứa hai phần tử con, nút và hộp danh sách. Hộp danh sách có thêm ba mục hộp danh sách con.
Cấu trúc cây trực quan
Trong WPF, khái niệm cây trực quan mô tả cấu trúc của các đối tượng trực quan, được biểu diễn bởi Lớp cơ sở trực quan. Nó biểu thị tất cả các phần tử giao diện người dùng được hiển thị trên màn hình đầu ra.
Khi một lập trình viên muốn tạo một khuôn mẫu cho một điều khiển cụ thể, anh ta thực sự đang hiển thị cây trực quan của điều khiển đó. Cây trực quan cũng rất hữu ích cho những người muốn vẽ các điều khiển cấp thấp hơn vì lý do hiệu suất và tối ưu hóa.
Trong các ứng dụng WPF, cây trực quan được sử dụng cho -
- Kết xuất các đối tượng trực quan.
- Kết xuất các bố cục.
- Các sự kiện được định tuyến chủ yếu đi dọc theo cây trực quan, không phải cây logic.
Để xem cây trực quan của ứng dụng đơn giản ở trên có chứa một nút và một hộp danh sách, hãy biên dịch và thực thi mã XAML và bạn sẽ thấy cửa sổ sau.
Khi ứng dụng đang chạy, bạn có thể thấy cây trực quan của ứng dụng đang chạy trong cửa sổ Live Visual Tree hiển thị hệ thống phân cấp hoàn chỉnh của ứng dụng này, như được hiển thị bên dưới.
Cây trực quan thường là một tập hợp siêu của cây logic. Bạn có thể thấy ở đây rằng tất cả các yếu tố logic cũng có trong cây trực quan. Vì vậy, hai cây này thực sự chỉ là hai khung nhìn khác nhau của cùng một tập hợp các đối tượng tạo nên giao diện người dùng.
Cây logic để lại rất nhiều chi tiết cho phép bạn tập trung vào cấu trúc cốt lõi của giao diện người dùng và bỏ qua các chi tiết về chính xác cách nó được trình bày.
Cây logic là những gì bạn sử dụng để tạo cấu trúc cơ bản của giao diện người dùng.
Cây trực quan sẽ được quan tâm nếu bạn đang tập trung vào bài thuyết trình. Ví dụ: nếu bạn muốn tùy chỉnh giao diện của bất kỳ phần tử giao diện người dùng nào, bạn sẽ cần sử dụng cây trực quan.
Trong các ứng dụng WPF, thuộc tính phụ thuộc là một loại thuộc tính cụ thể mở rộng thuộc tính CLR. Nó tận dụng lợi thế của các chức năng cụ thể có sẵn trong hệ thống thuộc tính WPF.
Một lớp xác định thuộc tính phụ thuộc phải được kế thừa từ DependencyObjectlớp học. 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ừDependencyObject lớp và chúng hỗ trợ các thuộc tính phụ thuộc, ví dụ: lớp Nút hỗ trợ IsMouseOver tài sản phụ thuộc.
Mã XAML sau tạo một nút với một số thuộc tính.
<Window x:Class = "WPFDependencyProperty.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFDependencyProperty"
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 của đối tượng, chẳng hạn như <Style TargetType = "{x: Type Button}">
Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ nhận được như sau MainWindow. Khi chuột ở trên 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.
Tại sao chúng ta cần thuộc tính phụ thuộc
Thuộc tính phụ thuộc mang lại cho bạn tất cả các loại lợi ích khi bạn sử dụng nó trong ứng dụng của mình. Thuộc tính phụ thuộc có thể được sử dụng trên thuộc tính CLR trong các trường hợp sau:
- Nếu bạn muốn thiết lập phong cách
- Nếu bạn muốn ràng buộc dữ liệu
- Nếu bạn muốn thiết lập bằng tài nguyên (tài nguyên tĩnh hoặc động)
- Nếu bạn muốn hỗ trợ hoạt hình
Về cơ bản, Thuộc tính phụ thuộc cung cấp rất nhiều chức năng mà bạn sẽ không có được bằng cách sử dụng thuộc tính CLR.
Sự khác biệt chính giữa dependency properties và khác CLR properties được liệt kê dưới đây -
Thuộc tính CLR có thể trực tiếp đọc / ghi từ thành viên riêng của một lớp bằng cách sử dụng getter và setter. Ngược lại, các thuộc tính phụ thuộc không được lưu trữ trong đố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.
Thuộc tính phụ thuộc tùy chỉnh
Trong .NET framework, các thuộc tính phụ thuộc tùy chỉnh cũng có thể được định nghĩa. Làm theo các bước dưới đây để xác định thuộc tính phụ thuộc tùy chỉnh trong C #.
Khai báo và đăng ký của bạn dependency property 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 static handler sẽ xử lý bất kỳ thay đổi nào xảy ra trên toàn cầu
Xác định một instance handler sẽ xử lý bất kỳ thay đổi nào xảy ra với phiên bản cụ thể đó.
Mã C # sau đây xác định một thuộc tính phụ thuộc để đặt SetText tài sản của người dùng kiểm soát.
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à khởi tạo SetText tài sản phụ thuộ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. Bạn có thể thấy ngay rằng trong MainWindow của chúng tôi, 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.
A routed eventlà một loại sự kiện có thể gọi các trình xử lý trên nhiều trình nghe trong một cây phần tử thay vì chỉ đối tượng đã tạo ra sự kiện. Về cơ bản, nó là một sự kiện CLR được hỗ trợ bởi một thể hiện của lớp Sự kiện định tuyến. Nó được đăng ký với hệ thống sự kiện WPF. RoutedEvents có ba chiến lược định tuyến chính như sau:
- Sự kiện trực tiếp
- Sự kiện bong bóng
- Sự kiện đường hầm
Sự kiện trực tiếp
Sự kiện trực tiếp tương tự như các sự kiện trong biểu mẫu Windows được nâng lên bởi phần tử mà sự kiện được tạo ra.
Không giống như sự kiện CLR tiêu chuẩn, các sự kiện được định tuyến trực tiếp hỗ trợ xử lý lớp và chúng có thể được sử dụng trong Bộ thiết lập sự kiện và Trình kích hoạt sự kiện theo kiểu Kiểm soát tùy chỉnh của bạn.
Một ví dụ điển hình về sự kiện trực tiếp là sự kiện MouseEnter.
Sự kiện bong bóng
Một sự kiện sôi sục bắt đầu với phần tử nơi bắt nguồn sự kiện. Sau đó, nó di chuyển lên cây trực quan đến phần tử trên cùng trong cây trực quan. Vì vậy, trong WPF, phần tử trên cùng rất có thể là một cửa sổ.
Sự kiện đường hầm
Các trình xử lý sự kiện trên gốc cây phần tử được gọi và sau đó sự kiện di chuyển xuống cây trực quan đến tất cả các nút con cho đến khi nó đến phần tử mà sự kiện bắt nguồn.
Sự khác biệt giữa sự kiện sủi bọt và sự kiện đào hầm là sự kiện đào hầm sẽ luôn bắt đầu bằng bản xem trước.
Trong ứng dụng WPF, các sự kiện thường được thực hiện dưới dạng một cặp tạo đường hầm / sủi bọt. Vì vậy, bạn sẽ có một bản MouseDown xem trước và sau đó là một sự kiện MouseDown.
Dưới đây là một ví dụ đơn giản về sự kiện Định tuyến trong đó một nút và ba khối văn bản được tạo với một số thuộc tính và sự kiện.
<Window x:Class = "WPFRoutedEvents.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "MainWindow" Height = "450" Width = "604" ButtonBase.Click = "Window_Click" >
<Grid>
<StackPanel Margin = "20" ButtonBase.Click = "StackPanel_Click">
<StackPanel Margin = "10">
<TextBlock Name = "txt1" FontSize = "18" Margin = "5" Text = "This is a TextBlock 1" />
<TextBlock Name = "txt2" FontSize = "18" Margin = "5" Text = "This is a TextBlock 2" />
<TextBlock Name = "txt3" FontSize = "18" Margin = "5" Text = "This is a TextBlock 3" />
</StackPanel>
<Button Margin = "10" Content = "Click me" Click = "Button_Click" Width = "80"/>
</StackPanel>
</Grid>
</Window>
Đây là mã C # để triển khai các sự kiện Click cho Button, StackPanel và Window.
using System.Windows;
namespace WPFRoutedEvents {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e) {
txt1.Text = "Button is Clicked";
}
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
}
private void Window_Click(object sender, RoutedEventArgs e) {
txt3.Text = "Click event is bubbled to Window";
}
}
}
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau:
Khi bạn nhấp vào nút, các khối văn bản sẽ được cập nhật, như hình dưới đây.
Nếu bạn muốn dừng sự kiện được định tuyến ở bất kỳ cấp độ cụ thể nào, thì bạn sẽ cần đặt e.Handled = true;
Hãy thay đổi StackPanel_Click sự kiện như hình dưới đây -
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
e.Handled = true;
}
Khi bạn nhấp vào nút, bạn sẽ quan sát thấy rằng sự kiện nhấp sẽ không được chuyển đến cửa sổ và sẽ dừng lại ở bảng điều khiển và khối văn bản thứ 3 sẽ không được cập nhật.
Sự kiện được định tuyến tùy chỉnh
Trong khuôn khổ .NET, sự kiện được định tuyến tùy chỉnh cũng có thể được xác định. Bạn cần làm theo các bước dưới đây để xác định sự kiện được định tuyến tùy chỉnh trong C #.
Khai báo và đăng ký sự kiện được định tuyến của bạn với lệnh gọi hệ thống RegisterRoutedEvent.
Chỉ định Chiến lược định tuyến, tức là Bong bóng, Đường hầm hoặc Trực tiếp.
Cung cấp trình xử lý sự kiện.
Hãy lấy một ví dụ để hiểu thêm về các sự kiện được định tuyến tùy chỉnh. Làm theo các bước dưới đây -
Tạo một dự án WPF mới với WPFCustomRoutedEvent
Nhấp chuột phải vào giải pháp của bạn và chọn Thêm> Mục mới ...
Hộp thoại sau sẽ mở ra, bây giờ hãy chọn Custom Control (WPF) và đặt tên cho nó MyCustomControl.
Nhấn vào Add và bạn sẽ thấy rằng hai tệp mới (Themes / Generic.xaml và MyCustomControl.cs) sẽ được thêm vào giải pháp của bạn.
Mã XAML sau đây đặt kiểu cho điều khiển tùy chỉnh trong tệp Generic.xaml.
<ResourceDictionary
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFCustomRoutedEvent">
<Style TargetType = "{x:Type local:MyCustomControl}">
<Setter Property = "Margin" Value = "50"/>
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate TargetType = "{x:Type local:MyCustomControl}">
<Border Background = "{TemplateBinding Background}"
BorderBrush = "{TemplateBinding BorderBrush}"
BorderThickness = "{TemplateBinding BorderThickness}">
<Button x:Name = "PART_Button" Content = "Click Me" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Dưới đây là mã C # cho MyCustomControl class kế thừa từ Control class trong đó sự kiện được định tuyến tùy chỉnh Nhấp chuột được tạo cho điều khiển tùy chỉnh.
using System.Windows;
using System.Windows.Controls;
namespace WPFCustomRoutedEvent {
public class MyCustomControl : Control {
static MyCustomControl() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl),
new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
public override void OnApplyTemplate() {
base.OnApplyTemplate();
//demo purpose only, check for previous instances and remove the handler first
var button = GetTemplateChild("PART_Button") as Button;
if (button ! = null)
button.Click + = Button_Click;
}
void Button_Click(object sender, RoutedEventArgs e) {
RaiseClickEvent();
}
public static readonly RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(MyCustomControl));
public event RoutedEventHandler Click {
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
}
protected virtual void RaiseClickEvent() {
RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent);
RaiseEvent(args);
}
}
}
Đây là triển khai sự kiện được định tuyến tùy chỉnh trong C # sẽ hiển thị một hộp thông báo khi người dùng nhấp vào nó.
using System.Windows;
namespace WPFCustomRoutedEvent {
// <summary>
// Interaction logic for MainWindow.xaml
// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void MyCustomControl_Click(object sender, RoutedEventArgs e) {
MessageBox.Show("It is the custom routed event of your custom control");
}
}
}
Đây là cách triển khai trong MainWindow.xaml để thêm điều khiển tùy chỉnh với một sự kiện được định tuyến Nhấp chuột.
<Window x:Class = "WPFCustomRoutedEvent.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFCustomRoutedEvent"
Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<local:MyCustomControl Click = "MyCustomControl_Click" />
</Grid>
</Window>
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra cửa sổ sau chứa điều khiển tùy chỉnh.
Khi bạn nhấp vào điều khiển tùy chỉnh, nó sẽ tạo ra thông báo sau.
Windows Presentation Foundation (WPF) cho phép các nhà phát triển dễ dàng xây dựng và tạo các ứng dụng dựa trên giao diện người dùng phong phú về mặt hình ảnh.
Các phần tử hoặc điều khiển giao diện người dùng cổ điển trong các khung giao diện người dùng khác cũng được nâng cao trong các ứng dụng WPF.
Tất cả các điều khiển WPF tiêu chuẩn có thể được tìm thấy trong Hộp công cụ là một phần của System.Windows.Controls.
Các điều khiển này cũng có thể được tạo bằng ngôn ngữ đánh dấu XAML.
Hệ thống phân cấp kế thừa hoàn chỉnh của các điều khiển WPF như sau:
Bảng sau đây chứa danh sách các điều khiển mà chúng ta sẽ thảo luận trong các chương tiếp theo.
Sơ không. | Điều khiển & Mô tả |
---|---|
1 | Cái nút Một điều khiển phản hồi thông tin nhập của người dùng |
2 | Lịch Đại diện cho một điều khiển cho phép người dùng chọn ngày bằng cách sử dụng màn hình lịch trực quan. |
3 | CheckBox Một điều khiển mà người dùng có thể chọn hoặc xóa. |
4 | ComboBox Danh sách thả xuống gồm các mục mà người dùng có thể chọn. |
5 | Danh mục Nhận hoặc đặt phần tử menu ngữ cảnh sẽ xuất hiện bất cứ khi nào menu ngữ cảnh được yêu cầu thông qua giao diện người dùng (UI) từ bên trong phần tử này. |
6 | Lưới dữ liệu Đại diện cho một điều khiển hiển thị dữ liệu trong một lưới có thể tùy chỉnh. |
7 | Bảng chọn ngày Điều khiển cho phép người dùng chọn ngày. |
số 8 | Hộp thoại Một ứng dụng cũng có thể hiển thị các cửa sổ bổ sung để giúp người dùng thu thập hoặc hiển thị thông tin quan trọng. |
9 | Chế độ hiển thị theo ô Một điều khiển trình bày một tập hợp các mục trong các hàng và cột có thể cuộn theo chiều ngang. |
10 | Hình ảnh Một điều khiển trình bày một hình ảnh. |
11 | Nhãn Hiển thị văn bản trên biểu mẫu. Cung cấp hỗ trợ cho các phím truy cập. |
12 | ListBox Một điều khiển trình bày danh sách nội tuyến các mục mà người dùng có thể chọn. |
13 | Thực đơn Đại diện cho một điều khiển menu Windows cho phép bạn tổ chức phân cấp các phần tử được liên kết với các lệnh và trình xử lý sự kiện. |
14 | PasswordBox Kiểm soát nhập mật khẩu. |
15 | Cửa sổ bật lên Hiển thị nội dung bên trên nội dung hiện có, trong giới hạn của cửa sổ ứng dụng. |
16 | Thanh tiến trình Một điều khiển cho biết tiến trình bằng cách hiển thị một thanh. |
17 | Nút radio Điều khiển cho phép người dùng chọn một tùy chọn từ một nhóm tùy chọn. |
18 | ScrollViewer Một điều khiển vùng chứa cho phép người dùng xoay và thu phóng nội dung của nó. |
19 | Thanh trượt Một điều khiển cho phép người dùng chọn từ một loạt các giá trị bằng cách di chuyển một điều khiển Ngón cái dọc theo một bản nhạc. |
20 | TextBlock Một điều khiển hiển thị văn bản. |
21 | Nút bật tắt Một nút có thể được chuyển đổi giữa 2 trạng thái. |
22 | Mẹo công cụ Một cửa sổ bật lên hiển thị thông tin cho một phần tử. |
23 | Cửa sổ Cửa sổ gốc cung cấp tùy chọn thu nhỏ / phóng to, Thanh tiêu đề, đường viền và nút đóng |
24 | Kiểm soát của bên thứ 3 Sử dụng các điều khiển của bên thứ ba trong các ứng dụng WPF của bạn. |
Chúng tôi sẽ thảo luận về tất cả các kiểm soát này từng cái một với việc triển khai chúng.
Bố cục của các điều khiển là rất quan trọng và quan trọng đối với khả năng sử dụng ứng dụng. Nó được sử dụng để sắp xếp một nhóm các phần tử GUI trong ứng dụng của bạn. Có một số điều quan trọng cần xem xét khi chọn bảng bố cục -
- Vị trí của các phần tử con
- Kích thước của các phần tử con
- Xếp lớp các phần tử con chồng chéo lên nhau
Sự sắp xếp pixel cố định của các điều khiển không hoạt động khi ứng dụng phải có độ phân giải màn hình khác nhau. XAML cung cấp một tập hợp phong phú các bảng bố cục tích hợp sẵn để sắp xếp các phần tử GUI theo cách thích hợp. Một số bảng bố cục thông dụng và phổ biến nhất như sau:
Sơ không. | Bảng và mô tả |
---|---|
1 | Bảng điều khiển ngăn xếp Bảng điều khiển ngăn xếp là một bảng điều khiển bố cục đơn giản và hữu ích trong XAML. Trong bảng điều khiển ngăn xếp, các phần tử con có thể được sắp xếp thành một dòng, theo chiều ngang hoặc chiều dọc, dựa trên thuộc tính định hướng. |
2 | Bảng điều khiển Trong WrapPanel, các phần tử con được định vị theo thứ tự tuần tự, từ trái sang phải hoặc từ trên xuống dưới dựa trên thuộc tính hướng. |
3 | Bảng điều khiển DockPanel xác định một khu vực để sắp xếp các phần tử con tương đối với nhau, theo chiều ngang hoặc chiều dọc. Với DockPanel, bạn có thể dễ dàng gắn các phần tử con lên trên, dưới, phải, trái và giữa bằng cách sử dụngDock bất động sản. |
4 | Bảng điều khiển canvas Bảng điều khiển canvas là bảng điều khiển bố cục cơ bản trong đó các phần tử con có thể được định vị một cách rõ ràng bằng cách sử dụng các tọa độ liên quan đến Canvas bất kỳ bên nào như trái, phải, trên và dưới. |
5 | Bảng điều khiển lưới Bảng điều khiển lưới cung cấp một khu vực linh hoạt bao gồm các hàng và cột. Trong Grid, các phần tử con có thể được sắp xếp dưới dạng bảng. |
Lồng bố cục có nghĩa là sử dụng bảng bố trí bên trong một bố cục khác, ví dụ: xác định bảng ngăn xếp bên trong lưới. Khái niệm này được sử dụng rộng rãi để tận dụng lợi thế của nhiều bố cục trong một ứng dụng. Trong ví dụ sau, chúng ta sẽ sử dụng các bảng ngăn xếp bên trong một lưới.
Hãy xem mã XAML sau đây.
<Window x:Class = "WPFNestingLayouts.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFNestingLayouts"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Grid Background = "AntiqueWhite">
<Grid.RowDefinitions>
<RowDefinition Height = "*" />
<RowDefinition Height = "*" />
<RowDefinition Height = "*" />
<RowDefinition Height = "*" />
<RowDefinition Height = "*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "*" />
</Grid.ColumnDefinitions>
<Label Content = "Employee Info" FontSize = "15"
FontWeight = "Bold" Grid.Column = "0" Grid.Row = "0"/>
<StackPanel Grid.Column = "0" Grid.Row = "1" Orientation = "Horizontal">
<Label Content = "Name" VerticalAlignment = "Center" Width = "70"/>
<TextBox Name = "txtName" Text = "Muhammad Ali" VerticalAlignment = "Center"
Width = "200">
</TextBox>
</StackPanel>
<StackPanel Grid.Column = "0" Grid.Row = "2" Orientation = "Horizontal">
<Label Content = "ID" VerticalAlignment = "Center" Width = "70"/>
<TextBox Name = "txtCity" Text = "421" VerticalAlignment = "Center"
Width = "50">
</TextBox>
</StackPanel>
<StackPanel Grid.Column = "0" Grid.Row = "3" Orientation = "Horizontal">
<Label Content = "Age" VerticalAlignment = "Center" Width = "70"/>
<TextBox Name = "txtState" Text = "32" VerticalAlignment = "Center"
Width = "50"></TextBox>
</StackPanel>
<StackPanel Grid.Column = "0" Grid.Row = "4" Orientation = "Horizontal">
<Label Content = "Title" VerticalAlignment = "Center" Width = "70"/>
<TextBox Name = "txtCountry" Text = "Programmer" VerticalAlignment = "Center"
Width = "200"></TextBox>
</StackPanel>
</Grid>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau.
Chúng tôi khuyên bạn nên thực thi mã ví dụ trên và thử các bố cục lồng nhau khác.
Windows Presentation Foundation (WPF) cung cấp một API mạnh mẽ với sự trợ giúp của các ứng dụng có thể nhận đầu vào từ các thiết bị khác nhau như chuột, bàn phím và bảng cảm ứng. Trong chương này, chúng ta sẽ thảo luận về các loại đầu vào sau có thể được xử lý trong các ứng dụng WPF:
Sơ không. | Đầu vào & Mô tả |
---|---|
1 | Chuột Có nhiều loại đầu vào chuột khác nhau như MouseDown, MouseEnter, MouseLeave, v.v. |
2 | Bàn phím Có nhiều loại đầu vào bàn phím như KeyDown, KeyUp, TextInput, v.v. |
3 | ContextMenu hoặc RoutedCommands RoutedCommands cho phép xử lý đầu vào ở cấp độ ngữ nghĩa hơn. Đây thực sự là những hướng dẫn đơn giản như Tạo mới, Mở, Sao chép, Cắt và Lưu. |
4 | Cảm ưng đa điểm Windows 7 và các phiên bản cao hơn của nó có khả năng nhận đầu vào từ nhiều thiết bị cảm ứng. Các ứng dụng WPF cũng có thể xử lý đầu vào cảm ứng dưới dạng đầu vào khác, chẳng hạn như chuột hoặc bàn phím, bằng cách nâng cao các sự kiện khi xảy ra chạm. |
Đối số dòng lệnh là một cơ chế trong đó người dùng có thể chuyển một tập hợp các tham số hoặc giá trị cho ứng dụng WPF khi nó được thực thi. Các đối số này rất quan trọng để điều khiển ứng dụng từ bên ngoài, ví dụ: nếu bạn muốn mở tài liệu Word từ dấu nhắc lệnh, thì bạn có thể sử dụng lệnh này “C:\> start winword word1.docx”Và nó sẽ mở ra word1.docx tài liệu.
Đối số dòng lệnh được xử lý trong hàm Khởi động. Sau đây là một ví dụ đơn giản cho thấy cách chuyển các đối số dòng lệnh vào ứng dụng WPF. Hãy tạo một ứng dụng WPF mới với tênWPFCommandLine.
Kéo một hộp văn bản từ hộp công cụ vào cửa sổ thiết kế.
Trong ví dụ này, chúng tôi sẽ chuyển một đường dẫn tệp txt đến ứng dụng của chúng tôi dưới dạng tham số dòng lệnh.
Chương trình sẽ đọc tệp txt và sau đó viết tất cả văn bản trên hộp văn bản.
Mã XAML sau đây tạo một hộp văn bản và khởi tạo nó với một số thuộc tính.
<Window x:Class = "WPFCommandLine.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFCommandLine"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">
<Grid>
<TextBox x:Name = "textBox" HorizontalAlignment = "Left"
Height = "180" Margin = "100" TextWrapping = "Wrap"
VerticalAlignment = "Top" Width = "300"/>
</Grid>
</Window>
- Bây giờ đăng ký sự kiện Khởi nghiệp trong tệp App.xaml như hình dưới đây.
<Application x:Class = "WPFCommandLine.App"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFCommandLine"
StartupUri = "MainWindow.xaml" Startup = "app_Startup">
<Application.Resources>
</Application.Resources>
</Application>
Dưới đây là việc triển khai sự kiện app_Startup trong App.xaml.cs sẽ nhận các đối số dòng lệnh.
using System.Windows;
namespace WPFCommandLine {
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application {
public static string[] Args;
void app_Startup(object sender, StartupEventArgs e) {
// If no command line arguments were provided, don't process them
if (e.Args.Length == 0) return;
if (e.Args.Length > 0) {
Args = e.Args;
}
}
}
}
Bây giờ, trong lớp MainWindow, chương trình sẽ mở tệp txt và viết tất cả văn bản trên hộp văn bản.
Nếu có một số lỗi được tìm thấy, thì chương trình sẽ hiển thị thông báo lỗi trên hộp văn bản.
using System;
using System.IO;
using System.Windows;
namespace WPFCommandLine {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
String[] args = App.Args;
try {
// Open the text file using a stream reader.
using (StreamReader sr = new StreamReader(args[0])) {
// Read the stream to a string, and write
// the string to the text box
String line = sr.ReadToEnd();
textBox.AppendText(line.ToString());
textBox.AppendText("\n");
}
}
catch (Exception e) {
textBox.AppendText("The file could not be read:");
textBox.AppendText("\n");
textBox.AppendText(e.Message);
}
}
}
}
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra một cửa sổ trống với một hộp văn bản vì chương trình này cần một đối số dòng lệnh. Vì vậy, Visual Studio cung cấp một cách dễ dàng để thực thi ứng dụng của bạn với các tham số dòng lệnh.
Nhấp chuột phải vào dự án WPF của bạn trong trình khám phá giải pháp và chọn thuộc tính, nó sẽ hiển thị cửa sổ sau.
Chọn tùy chọn Gỡ lỗi và ghi đường dẫn tệp trong đối số Dòng lệnh.
Tạo tệp txt với Test.txt và viết một số văn bản trong tệp đó và lưu nó vào bất kỳ vị trí nào. Trong trường hợp này, tệp txt được lưu trên “D:\" ổ cứng.
Lưu các thay đổi trong dự án của bạn và biên dịch và thực thi ứng dụng của bạn ngay bây giờ. Bạn sẽ thấy văn bản trong TextBox mà chương trình đọc từ tệp Text.txt.
Bây giờ, hãy thử và thay đổi tên tệp trên máy của bạn từ Test.txt đến Test1.txt và thực thi lại chương trình của bạn, sau đó bạn sẽ thấy thông báo lỗi đó trong hộp văn bản.
Chúng tôi khuyên bạn nên thực thi mã trên và làm theo tất cả các bước để thực thi ứng dụng của bạn thành công.
Liên kết dữ liệu là một cơ chế trong ứng dụng WPF cung cấp một cách đơn giản và dễ dàng để các ứng dụng Windows Runtime hiển thị và tương tác với dữ liệu. Trong cơ chế này, việc quản lý dữ liệu hoàn toàn tách biệt với cách dữ liệu.
Liên kết dữ liệu cho phép luồng dữ liệu giữa các phần tử UI và đối tượng dữ liệu trên giao diện người dùng. Khi một ràng buộc được thiết lập và dữ liệu hoặc mô hình kinh doanh của bạn thay đổi, thì nó sẽ phản ánh các cập nhật tự động cho các phần tử UI và ngược lại. Cũng có thể liên kết, không phải với nguồn dữ liệu chuẩn mà với một phần tử khác trên trang.
Liên kết dữ liệu có hai loại - one-way data binding và two-way data binding.
Liên kết dữ liệu một chiều
Trong liên kết một chiều, dữ liệu được liên kết từ nguồn của nó (đó là đối tượng chứa dữ liệu) với đích của nó (đó là đối tượng hiển thị dữ liệu)
Hãy lấy một ví dụ đơn giản để hiểu chi tiết ràng buộc dữ liệu một chiều. Trước hết, hãy tạo một dự án WPF mới với tênWPFDataBinding.
Mã XAML sau đây tạo ra hai nhãn, hai hộp văn bản và một nút và khởi tạo chúng với một số thuộc tính.
<Window x:Class = "WPFDataBinding.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFDataBinding"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition Height = "Auto" />
<RowDefinition Height = "*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "200" />
</Grid.ColumnDefinitions>
<Label Name = "nameLabel" Margin = "2">_Name:</Label>
<TextBox Name = "nameText" Grid.Column = "1" Margin = "2"
Text = "{Binding Name, Mode = OneWay}"/>
<Label Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</Label>
<TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2"
Text = "{Binding Age, Mode = OneWay}"/>
<StackPanel Grid.Row = "2" Grid.ColumnSpan = "2">
<Button Content = "_Show..." Click="Button_Click" />
</StackPanel>
</Grid>
</Window>
Thuộc tính văn bản của cả hộp văn bản liên kết với “Tên” và “Tuổi”, là các biến lớp của lớp Người được hiển thị bên dưới.
Trong lớp Person, chúng ta chỉ có hai biến Name và Agevà đối tượng của nó được khởi tạo trong MainWindow lớp học.
Trong mã XAML, chúng tôi liên kết với một thuộc tính Tên và Tuổi, nhưng chúng tôi chưa chọn thuộc tính đó thuộc đối tượng nào.
Cách dễ dàng hơn là gán một đối tượng cho DataContext thuộc tính mà chúng tôi đang ràng buộc trong mã C # sau trong MainWindowconstructor.
using System.Windows;
namespace WPFDataBinding {
public partial class MainWindow : Window {
Person person = new Person { Name = "Salman", Age = 26 };
public MainWindow() {
InitializeComponent();
this.DataContext = person;
}
private void Button_Click(object sender, RoutedEventArgs e) {
string message = person.Name + " is " + person.Age;
MessageBox.Show(message);
}
}
public class Person {
private string nameValue;
public string Name {
get { return nameValue; }
set { nameValue = value; }
}
private double ageValue;
public double Age {
get { return ageValue; }
set {
if (value != ageValue) {
ageValue = value;
}
}
}
}
}
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 chúng tôi đã liên kết thành công với Tên và Tuổi của đối tượng Người đó.
Khi bạn nhấn Show , nó sẽ hiển thị tên và tuổi trên hộp tin nhắn.
Hãy thay đổi Tên và Tuổi trong hộp thoại.
Nếu bây giờ bạn nhấp vào nút Hiển thị, nó sẽ lại hiển thị cùng một thông báo.
Điều này bởi vì chế độ liên kết dữ liệu được đặt thành một chiều trong mã XAML. Để hiển thị dữ liệu cập nhật, bạn sẽ cần hiểu ràng buộc dữ liệu hai chiều.
Liên kết dữ liệu hai chiều
Trong ràng buộc hai chiều, người dùng có thể sửa đổi dữ liệu thông qua giao diện người dùng và cập nhật dữ liệu đó trong nguồn. Nếu nguồn thay đổi trong khi người dùng đang xem dạng xem, bạn muốn dạng xem được cập nhật.
Hãy lấy cùng một ví dụ nhưng ở đây, chúng ta sẽ thay đổi chế độ ràng buộc từ Một chiều sang Hai chiều trong mã XAML.
<Window x:Class = "WPFDataBinding.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFDataBinding"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition Height = "Auto" />
<RowDefinition Height = "*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "200" />
</Grid.ColumnDefinitions>
<Label Name = "nameLabel" Margin = "2">_Name:</Label>
<TextBox Name = "nameText" Grid.Column = "1" Margin = "2"
Text = "{Binding Name, Mode = TwoWay}"/>
<Label Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</Label>
<TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2"
Text = "{Binding Age, Mode = TwoWay}"/>
<StackPanel Grid.Row = "2" Grid.ColumnSpan = "2">
<Button Content = "_Show..." Click = "Button_Click" />
</StackPanel>
</Grid>
</Window>
Hãy chạy lại ứng dụng này.
Nó sẽ tạo ra cùng một đầu ra -
Bây giờ chúng ta hãy thay đổi các giá trị Tên và Tuổi -
Nếu bạn nhấp vào nút Hiển thị ngay bây giờ, nó sẽ hiển thị thông báo cập nhật.
Chúng tôi khuyên bạn nên thực thi đoạn mã trên với cả hai trường hợp để hiểu rõ hơn về khái niệm.
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. Đó là 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. Điều đó có nghĩa là đối tượng có thể được sử dụng lại. 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 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.
Tài nguyên có thể có hai loại -
- StaticResource
- DynamicResource
StaticResource là dạng tra cứu một lần, trong khi DynamicResource hoạt động giống như một liên kết dữ liệu hơn. Nó ghi nhớ rằng một thuộc tính được liên kết với một khóa tài nguyên cụ thể. Nếu đối tượng được liên kết với khóa đó thay đổi, tài nguyên động sẽ cập nhật thuộc tính đích.
Thí dụ
Đây là một ứng dụng đơn giản cho tài nguyên SolidColorBrush.
Hãy tạo một dự án WPF mới với tên WPFResouces.
Kéo hai Hình chữ nhật và đặt thuộc tính của chúng như được hiển thị trong mã XAML sau đây.
<Window x:Class = "WPFResources.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFResources"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">
<Window.Resources>
<SolidColorBrush x:Key = "brushResource" Color = "Blue" />
</Window.Resources>
<StackPanel>
<Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}" />
<Rectangle Height = "50" Margin = "20" Fill = "{DynamicResource brushResource}" />
<Button x:Name = "changeResourceButton"
Content = "_Change Resource" Click = "changeResourceButton_Click" />
</StackPanel>
</Window>
Trong đoạn mã XAML ở trên, bạn có thể thấy một hình chữ nhật có StaticResource và hình chữ nhật kia có DynamicResource và màu của brushResource là Bisque.
Khi bạn biên dịch và thực thi mã, nó sẽ tạo ra MainWindow sau.
Khi bạn nhấp vào nút "Thay đổi tài nguyên", bạn sẽ thấy rằng hình chữ nhật có DynamicResource sẽ đổi màu thành Đỏ.
Phạm vi tài nguyên
Tài nguyên được định nghĩa trong resource dictionaries, nhưng có rất nhiều nơi mà từ điển tài nguyên có thể được xác định. 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 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. Đó 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.
Liên quan đến 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.
Ứng dụng trên có tài nguyên ở cấp Cửa sổ / trang của nó.
Từ điển tài nguyên
Từ điển tài nguyên trong ứng dụng XAML ngụ ý rằng từ điển tài nguyên được lưu 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 cách nào để chúng ta 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? 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 bằng cách làm theo các bước dưới đây:
Trong giải pháp của bạn, hãy thêm một thư mục mới và đặt tên cho nó ResourceDictionaries.
Nhấp chuột phải vào thư mục này và chọn Từ điển Tài nguyên từ Thêm mục menu con và đặt tên cho nó DictionaryWithBrush.xaml
Thí dụ
Bây giờ chúng ta hãy lấy cùng một ví dụ, nhưng ở đây, chúng ta sẽ xác định từ điển tài nguyên ở cấp ứng dụng. Mã XAML cho MainWindow.xaml như sau:
<Window x:Class = "WPFResources.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFResources"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">
<StackPanel>
<Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}" />
<Rectangle Height = "50" Margin = "20" Fill = "{DynamicResource brushResource}" />
<Button x:Name = "changeResourceButton"
Content = "_Change Resource" Click = "changeResourceButton_Click" />
</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 x:Key = "brushResource" Color = "Blue" />
</ResourceDictionary>
Đây là cách triển khai trong app.xaml -
<Application x:Class="WPFResources.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:
Khi bạn nhấp vào nút Thay đổi tài nguyên, hình chữ nhật sẽ đổi màu thành Đỏ.
Chúng tôi khuyên bạn nên thực thi mã trên và thử thêm một số tài nguyên (ví dụ: màu nền).
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ó để làm cho điều khiển xuất hiện. Trong các ứng dụng WPF, 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ữastyles và templates được liệt kê dưới đây -
Kiểu chỉ có thể thay đổi giao diện đ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 thường được sử dụng 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 hình thứ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 và cũng có giao diện mặc định của nút có thể được thay đổi bởi Mẫu điều khiển.
Thí dụ
Hãy lấy một ví dụ đơn giản. Chúng tôi sẽ tạo hai nút (một là với mẫu và một là nút mặc định) và khởi tạo chúng với một số thuộc tí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 bạn biên dịch và thực thi đoạn mã trên, nó sẽ hiển thị MainWindow sau.
Khi bạn di chuyển chuột qua nút có mẫu tùy chỉnh, nó sẽ thay đổi màu sắc như hình bên dưới.
Mẫu dữ liệu
Mẫu Dữ liệu xác định và chỉ định hình thức và cấu trúc của một 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.
Thí dụ
Hãy lấy một ví dụ đơn giản để hiểu khái niệm về mẫu dữ liệu. Tạo một dự án WPF mới với tênWPFDataTemplates.
Trong mã XAML sau đây, chúng ta sẽ tạo Mẫu dữ liệu làm tài nguyên để chứa các nhãn và hộp văn bản. Có một nút và một hộp danh sách để hiển thị dữ liệu.
<Window x:Class = "WPFDataTemplates.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFDataTemplates"
xmlns:loc = "clr-namespace:WPFDataTemplates"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">
<Window.Resources>
<DataTemplate DataType = "{x:Type loc:Person}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition Height = "Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "200" />
</Grid.ColumnDefinitions>
<Label Name = "nameLabel" Margin = "10"/>
<TextBox Name = "nameText" Grid.Column = "1" Margin = "10"
Text = "{Binding Name}"/>
<Label Name = "ageLabel" Margin = "10" Grid.Row = "1"/>
<TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "10"
Text = "{Binding Age}"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto" />
<RowDefinition Height = "*" />
</Grid.RowDefinitions>
<ListBox ItemsSource = "{Binding}" />
<StackPanel Grid.Row = "1" >
<Button Content = "_Show..." Click = "Button_Click" Width = "80" HorizontalAlignment = "Left" Margin = "10"/>
</StackPanel>
</Grid>
</Window>
Đây là implementation in C# trong đó danh sách các đối tượng Person được gán cho DataContext, việc thực hiện lớp Person và sự kiện bấm vào nút.
using System.Collections.Generic;
using System.Windows;
namespace WPFDataTemplates {
public partial class MainWindow : Window {
Person src = new Person { Name = "Ali", Age = 27 };
List<Person> people = new List<Person>();
public MainWindow() {
InitializeComponent();
people.Add(src);
people.Add(new Person { Name = "Mike", Age = 62 });
people.Add(new Person { Name = "Brian", Age = 12 });
this.DataContext = people;
}
private void Button_Click(object sender, RoutedEventArgs e) {
string message = src.Name + " is " + src.Age;
MessageBox.Show(message);
}
}
public class Person {
private string nameValue;
public string Name {
get { return nameValue; }
set { nameValue = value; }
}
private double ageValue;
public double Age {
get { return ageValue; }
set {
if (value != ageValue) {
ageValue = value;
}
}
}
}
}
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau. Nó chứa một danh sách và bên trong hộp danh sách, mỗi mục hộp danh sách chứa dữ liệu đối tượng lớp Người được hiển thị trên Nhãn và hộp Văn bản.
Khuôn khổ .NET cung cấp một số chiến lược để cá nhân hóa và tùy chỉnh giao diện của ứng dụng. Kiểu cung cấp cho chúng ta sự linh hoạt để đặt một số thuộc tính của một đối tượng và sử dụng lại các cài đặt cụ thể này trên nhiều đối tượng để có giao diện nhất quán.
Trong kiểu, bạn chỉ có thể đặt các thuộc tính hiện có của một đối tượng như Chiều cao, Chiều rộng, Kích thước phông chữ, v.v.
Chỉ có thể chỉ định hành vi mặc định của điều khiển.
Nhiều thuộc tính có thể được thêm vào một kiểu duy nhất.
Các kiểu được sử dụng để mang lại giao diện hoặc giao diện đồng nhất cho một bộ điều khiển. Các kiểu ngầm định được sử dụng để áp dụng diện mạo cho tất cả các điều khiển của một kiểu nhất định và đơn giản hóa ứng dụng. Hãy tưởng tượng ba nút, tất cả chúng phải trông giống nhau, cùng chiều rộng và chiều cao, cùng cỡ chữ, cùng màu nền trước, v.v. Chúng ta có thể đặt tất cả các thuộc tính đó trên chính các phần tử của nút và điều đó vẫn khá ổn cho tất cả các nút. Hãy xem sơ đồ sau.
Nhưng trong các ứng dụng đời thực, thông thường bạn sẽ có nhiều thứ cần phải giống hệt nhau. Và tất nhiên không chỉ có các nút, bạn thường muốn các khối văn bản, hộp văn bản và hộp tổ hợp, v.v. của mình trông giống nhau trên ứng dụng của bạn. Chắc chắn, phải có một cách tốt hơn để đạt được điều này và nó được gọi làstyling. Bạn có thể coi kiểu như một cách thuận tiện để áp dụng một tập hợp các giá trị thuộc tính cho nhiều phần tử. Hãy xem sơ đồ sau.
Thí dụ
Hãy lấy một ví dụ đơn giản để hiểu khái niệm này. Bắt đầu bằng cách tạo một dự án WPF mới.
Kéo ba nút từ hộp công cụ vào cửa sổ thiết kế.
Đoạn mã XAML sau tạo ba nút và khởi tạo chúng với một số thuộc tính.
<Window x:Class = "WPFStyle.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace: WPFStyle"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<StackPanel>
<Button Content = "Button1" Height = "30" Width = "80"
Foreground = "Blue" FontSize = "12" Margin = "10"/>
<Button Content = "Button2" Height = "30" Width = "80"
Foreground = "Blue" FontSize = "12" Margin = "10"/>
<Button Content = "Button3" Height = "30" Width = "80"
Foreground = "Blue" FontSize = "12" Margin = "10"/>
</StackPanel>
</Window>
Khi bạn nhìn vào đoạn mã trên, bạn sẽ thấy rằng tất cả các nút chiều cao, chiều rộng, màu nền trước, kích thước phông chữ và thuộc tính lề đều giống nhau. Bây giờ khi đoạn mã trên được biên dịch và thực thi, cửa sổ sau sẽ được hiển thị.
Bây giờ chúng ta hãy xem xét cùng một ví dụ, nhưng lần này, chúng ta sẽ sử dụng style.
<Window x:Class = "XAMLStyle.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:XAMLStyle"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Window.Resources>
<Style x:Key = "myButtonStyle" TargetType = "Button">
<Setter Property = "Height" Value = "30" />
<Setter Property = "Width" Value = "80" />
<Setter Property = "Foreground" Value = "Blue" />
<Setter Property = "FontSize" Value = "12" />
<Setter Property = "Margin" Value = "10" />
</Style>
</Window.Resources>
<StackPanel>
<Button Content = "Button1" Style = "{StaticResource myButtonStyle}" />
<Button Content = "Button2" Style = "{StaticResource myButtonStyle}" />
<Button Content = "Button3" Style="{StaticResource myButtonStyle}" />
</StackPanel>
</Window>
Kiểu được định nghĩa trong từ điển tài nguyên và mỗi kiểu có một mã định danh khóa duy nhất và một kiểu đích. Bên trong <style>, bạn có thể thấy rằng nhiều thẻ setter được xác định cho từng thuộc tính sẽ được bao gồm trong kiểu.
Trong ví dụ trên, tất cả các thuộc tính chung của mỗi nút hiện được xác định theo kiểu và sau đó kiểu được gán cho mỗi nút bằng một khóa duy nhất bằng cách đặt thuộc tính kiểu thông qua tiện ích mở rộng đánh dấu StaticResource.
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ hiển thị cửa sổ sau (cùng một đầu ra).
Lợi thế của việc làm như thế này là rõ ràng ngay lập tức, chúng ta có thể sử dụng lại phong cách đó ở bất cứ đâu trong phạm vi của nó; và nếu chúng ta cần thay đổi nó, chúng ta chỉ cần thay đổi nó một lần trong định nghĩa kiểu thay vì trên từng phần tử.
Ở cấp độ nào, một phong cách được xác định ngay lập tức sẽ giới hạn phạm vi của phong cách đó. Vì vậy, phạm vi, tức là nơi bạn có thể sử dụng kiểu, phụ thuộc vào nơi bạn đã xác định nó. Phong cách có thể được xác định ở các cấp độ sau:
Sr.No | Cấp độ & Mô tả |
---|---|
1 | Mức độ kiểm soát Chỉ có thể áp dụng việc xác định kiểu ở cấp độ điều khiển cho điều khiển cụ thể đó. Dưới đây là một ví dụ về cấp độ điều khiển trong đó nút và TextBlock có kiểu riêng. |
2 | Cấp độ bố cục Việc xác định một kiểu ở bất kỳ cấp độ bố cục nào sẽ làm cho nó có thể truy cập được bởi bố cục đó và chỉ các phần tử con của nó. |
3 | Mức cửa sổ Việc xác định một kiểu ở cấp cửa sổ có thể làm cho tất cả các phần tử trên cửa sổ đó có thể truy cập được. |
4 | Mức độ ứng dụng Việc xác định một kiểu ở cấp ứng dụng có thể làm cho nó có thể truy cập được trong toàn bộ ứng dụng. Hãy lấy cùng một ví dụ, nhưng ở đây, chúng tôi sẽ đặt các kiểu trong tệp app.xaml để làm cho nó có thể truy cập được trong toàn bộ ứng dụng. |
Về cơ bản, một trình kích hoạt cho phép bạn thay đổi giá trị thuộc tính hoặc thực hiện các hành động dựa trên giá trị của thuộc tính. Vì vậy, nó cho phép bạn tự động thay đổi giao diện và / hoặc hành vi của điều khiển của mình mà không cần phải tạo mới.
Trình kích hoạt được sử dụng để thay đổi giá trị của bất kỳ thuộc tính nhất định nào, khi các điều kiện nhất định được thỏa mãn. Các trình kích hoạt thường được xác định trong một kiểu hoặc trong thư mục gốc của tài liệu được áp dụng cho điều khiển cụ thể đó. Có ba loại trình kích hoạt -
- Kích hoạt thuộc tính
- Kích hoạt dữ liệu
- Trình kích hoạt sự kiện
Kích hoạt thuộc tính
Trong trình kích hoạt thuộc tính, khi một thay đổi xảy ra trong một thuộc tính, nó sẽ mang lại thay đổi tức thì hoặc thay đổi động trong một thuộc tính khác. Ví dụ: bạn có thể sử dụng trình kích hoạt thuộc tính để thay đổi giao diện của nút khi chuột di chuột qua nút.
Đoạn mã ví dụ sau cho biết cách thay đổi màu nền trước của nút khi di chuột qua nút.
<Window x:Class = "WPFPropertyTriggers.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>
<Style x:Key = "TriggerStyle" TargetType = "Button">
<Setter Property = "Foreground" Value = "Blue" />
<Style.Triggers>
<Trigger Property = "IsMouseOver" Value = "True">
<Setter Property = "Foreground" Value = "Green" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button Width = "100" Height = "70"
Style = "{StaticResource TriggerStyle}" Content = "Trigger"/>
</Grid>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau:
Khi di chuột qua nút, màu nền trước của nó sẽ chuyển thành màu xanh lục.
Kích hoạt dữ liệu
Trình kích hoạt dữ liệu thực hiện một số hành động khi dữ liệu bị ràng buộc thỏa mãn một số điều kiện. Hãy xem đoạn mã XAML sau, trong đó hộp kiểm và khối văn bản được tạo với một số thuộc tính. Khi hộp kiểm được chọn, nó sẽ thay đổi màu nền trước của nó thành màu đỏ.
<Window x:Class = "WPFDataTrigger.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "Data Trigger" Height = "350" Width = "604">
<StackPanel HorizontalAlignment = "Center">
<CheckBox x:Name = "redColorCheckBox"
Content = "Set red as foreground color" Margin = "20"/>
<TextBlock Name = "txtblock" VerticalAlignment = "Center"
Text = "Event Trigger" FontSize = "24" Margin = "20">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding = "{Binding ElementName = redColorCheckBox, Path = IsChecked}"
Value = "true">
<Setter Property = "TextBlock.Foreground" Value = "Red"/>
<Setter Property = "TextBlock.Cursor" Value = "Hand" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</Window>
Khi đoạn mã trên được biên dịch và thực thi, nó sẽ tạo ra kết quả sau:
Khi bạn đánh dấu vào hộp kiểm, khối văn bản sẽ thay đổi màu nền trước của nó thành màu đỏ.
Trình kích hoạt sự kiện
Trình kích hoạt sự kiện thực hiện một số hành động khi một sự kiện cụ thể được kích hoạt. Nó thường được sử dụng để thực hiện một số hoạt ảnh trên điều khiển như DoubleAnumatio, ColorAnimation, v.v. Trong ví dụ sau, chúng ta sẽ tạo một nút đơn giản. Khi sự kiện nhấp chuột được kích hoạt, nó sẽ mở rộng chiều rộng và chiều cao của nút.
<Window x:Class = "WPFEventTrigger.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>
<Button Content = "Click Me" Width = "60" Height = "30">
<Button.Triggers>
<EventTrigger RoutedEvent = "Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
"Width" Duration = "0:0:4">
<LinearDoubleKeyFrame Value = "60" KeyTime = "0:0:0"/>
<LinearDoubleKeyFrame Value = "120" KeyTime = "0:0:1"/>
<LinearDoubleKeyFrame Value = "200" KeyTime = "0:0:2"/>
<LinearDoubleKeyFrame Value = "300" KeyTime = "0:0:3"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Height"
Duration = "0:0:4">
<LinearDoubleKeyFrame Value = "30" KeyTime = "0:0:0"/>
<LinearDoubleKeyFrame Value = "40" KeyTime = "0:0:1"/>
<LinearDoubleKeyFrame Value = "80" KeyTime = "0:0:2"/>
<LinearDoubleKeyFrame Value = "150" KeyTime = "0:0:3"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau:
Khi nhấp vào nút, bạn sẽ thấy rằng nó sẽ bắt đầu mở rộng theo cả hai chiều.
Chúng tôi khuyên bạn nên biên dịch và thực thi các ví dụ trên, đồng thời áp dụng các trình kích hoạt cho các thuộc tính khác.
Nó là một cơ chế có hệ thống để xác định và sửa các lỗi hoặc khiếm khuyết trong một đoạn mã không hoạt động giống như bạn mong đợi. Gỡ lỗi một ứng dụng phức tạp trong đó các hệ thống con được kết hợp chặt chẽ với nhau không dễ dàng như vậy, vì việc sửa lỗi trong một hệ thống con có thể tạo ra lỗi trong hệ thống con khác.
Gỡ lỗi trong C #
Trong các ứng dụng WPF, lập trình viên xử lý hai ngôn ngữ như C # và XAML. Nếu bạn đã quen với việc gỡ lỗi bằng bất kỳ ngôn ngữ thủ tục nào như C # hoặc C / C ++ và bạn cũng biết cách sử dụng các điểm ngắt, thì bạn có thể gỡ lỗi phần C # trong ứng dụng của mình một cách dễ dàng.
Hãy lấy một ví dụ đơn giản để minh họa cách gỡ lỗi mã C #. Tạo một dự án WPF mới với tênWPFDebuggingDemo. Kéo bốn nhãn, ba hộp văn bản và một nút từ hộp công cụ. Hãy xem mã XAML sau đây.
<Window x:Class = "WPFDebuggingDemo.Window1"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "Window1" Height = "400" Width = "604">
<Grid>
<TextBox Height = "23" Margin = "0,44,169,0" Name = "textBox1"
VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120" />
<TextBox Height = "23" Margin = "0,99,169,0" Name = "textBox2"
VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120" />
<TextBox HorizontalAlignment = "Right" Margin = "0,153,169,0"
Name = "textBox3" Width = "120" Height = "23" VerticalAlignment = "Top" />
<Label Height = "28" Margin = "117,42,0,0" Name = "label1"
VerticalAlignment = "Top" HorizontalAlignment = "Left" Width = "120">
Item 1</Label>
<Label Height = "28" HorizontalAlignment = "Left"
Margin = "117,99,0,0" Name = "label2" VerticalAlignment = "Top" Width = "120">
Item 2</Label>
<Label HorizontalAlignment = "Left" Margin = "117,153,0,181"
Name = "label3" Width = "120">Item 3</Label>
<Button Height = "23" HorizontalAlignment = "Right" Margin = "0,0,214,127"
Name = "button1" VerticalAlignment = "Bottom" Width = "75"
Click = "button1_Click">Total</Button>
<Label Height = "28" HorizontalAlignment = "Right"
Margin = "0,0,169,66" Name = "label4" VerticalAlignment = "Bottom" Width = "120"/>
</Grid>
</Window>
Dưới đây là mã C # trong đó sự kiện nhấp vào nút được triển khai.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 WPFDebuggingDemo {
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e) {
if (textBox1.Text.Length > 0 && textBox2.Text.Length > 0 && textBox2.Text.Length > 0) {
double total = Convert.ToDouble(textBox1.Text) +
Convert.ToDouble(textBox2.Text) + Convert.ToDouble(textBox3.Text);
label4.Content = total.ToString();
}
else {
MessageBox.Show("Enter the value in all field.");
}
}
}
}
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau. Bây giờ, hãy nhập các giá trị vào các hộp văn bản và nhấn nút Total. Bạn sẽ nhận được tổng giá trị sau khi tổng hợp tất cả các giá trị được nhập vào các hộp văn bản.
Nếu bạn cố gắng nhập các giá trị khác với giá trị thực, thì ứng dụng trên sẽ bị lỗi. Để tìm và giải quyết vấn đề (tại sao nó bị lỗi), bạn có thể chèn các điểm ngắt vào sự kiện nhấp vào nút.
Hãy viết "abc" trong mục 1 như hình dưới đây.
Khi nhấp vào nút Total, bạn sẽ thấy rằng chương trình dừng lại ở điểm ngắt
Bây giờ di chuyển con trỏ về phía textbox1.Text và bạn sẽ thấy rằng chương trình đang cố gắng thêm abc giá trị với các giá trị khác, đó là lý do tại sao chương trình bị treo.
Gỡ lỗi trong XAML
Nếu bạn đang mong đợi loại gỡ lỗi tương tự trong XAML, thì bạn sẽ ngạc nhiên khi biết rằng không thể gỡ lỗi mã XAML giống như gỡ lỗi bất kỳ mã ngôn ngữ thủ tục nào khác. Khi bạn nghe thấy thuật ngữ gỡ lỗi trong mã XAML, điều đó có nghĩa là hãy thử và tìm lỗi.
Trong liên kết dữ liệu, dữ liệu của bạn không hiển thị trên màn hình và bạn không biết tại sao
Hoặc một vấn đề có liên quan đến bố cục phức tạp.
Hoặc vấn đề căn chỉnh hoặc các vấn đề về màu lề, lớp phủ, v.v. với một số mẫu mở rộng như ListBox và hộp tổ hợp.
Gỡ lỗi chương trình XAML là điều bạn thường làm để kiểm tra xem các ràng buộc của bạn có hoạt động hay không; và nếu nó không hoạt động, sau đó để kiểm tra xem có gì sai không. Rất tiếc, không thể thiết lập các điểm ngắt trong liên kết XAML ngoại trừ trong Silverlight, nhưng chúng tôi có thể sử dụng cửa sổ Đầu ra để kiểm tra lỗi liên kết dữ liệu. Chúng ta hãy xem mã XAML sau để tìm lỗi trong liên kết dữ liệu.
<Window x:Class = "DataBindingOneWay.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>
<StackPanel Name = "Display">
<StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0">
<TextBlock Text = "Name: " Margin = "10" Width = "100"/>
<TextBlock Margin = "10" Width = "100" Text = "{Binding FirstName}"/>
</StackPanel>
<StackPanel Orientation = "Horizontal" Margin = "50,0,50,0">
<TextBlock Text = "Title: " Margin = "10" Width = "100"/>
<TextBlock Margin = "10" Width = "100" Text = "{Binding Title}" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
Thuộc tính văn bản của hai khối văn bản được đặt tĩnh thành “Tên” và “Tiêu đề”, trong khi hai khối văn bản khác Thuộc tính văn bản được liên kết với “FirstName” và “Title” nhưng các biến lớp là Tên và Tiêu đề trong lớp Nhân viên được hiển thị bên dưới.
Chúng tôi đã cố ý viết một tên biến không chính xác để hiểu chúng tôi có thể tìm thấy loại lỗi này ở đâu khi đầu ra mong muốn không được hiển thị.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataBindingOneWay {
public class Employee {
public string Name { get; set; }
public string Title { get; set; }
public static Employee GetEmployee() {
var emp = new Employee() {
Name = "Ali Ahmed", Title = "Developer"
};
return emp;
}
}
}
Đây là phần triển khai của lớp MainWindow trong mã C #.
using System;
using System.Windows;
using System.Windows.Controls;
namespace DataBindingOneWay {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = Employee.GetEmployee();
}
}
}
Hãy chạy ứng dụng này và bạn có thể thấy ngay trong MainWindow của chúng ta rằng chúng ta đã liên kết thành công với Tiêu đề của đối tượng Nhân viên đó nhưng tên không bị ràng buộc.
Để kiểm tra điều gì đã xảy ra với tên, hãy nhìn vào cửa sổ đầu ra nơi có rất nhiều nhật ký được tạo.
Dễ dàng tìm thấy lỗi chỉ là tìm kiếm lỗi và bạn sẽ tìm thấy lỗi sau có nội dung “Lỗi đường dẫn BindingExpression: không tìm thấy thuộc tính 'FirstName' trên 'đối tượng' '' Nhân viên”
System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName'
property not found on 'object' ''Employee' (HashCode=11611730)'.
BindingExpression:Path = FirstName; DataItem = 'Employee' (HashCode = 11611730);
target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
Điều này chỉ ra rõ ràng rằng FirstName không phải là thành viên của lớp Nhân viên, vì vậy nó giúp khắc phục loại sự cố này trong ứng dụng của bạn.
Khi bạn thay đổi FirstName thành Name một lần nữa, bạn sẽ thấy kết quả đầu ra mong muốn.
Công cụ gỡ lỗi giao diện người dùng cho XAML
Công cụ gỡ lỗi giao diện người dùng đã được giới thiệu cho XAML với Visual Studio 2015 để kiểm tra mã XAML trong thời gian chạy. Với sự trợ giúp của các công cụ này, mã XAML được trình bày dưới dạng cây trực quan của ứng dụng WPF đang chạy của bạn và cả các thuộc tính phần tử giao diện người dùng khác nhau trong cây. Để bật các công cụ này, hãy làm theo các bước dưới đây.
- Chuyển đến menu Công cụ và chọn Tùy chọn từ menu Công cụ.
- Nó sẽ mở hộp thoại sau.
- Chuyển đến Tùy chọn chung trong mục Gỡ lỗi ở phía bên trái.
- Đánh dấu vào tùy chọn được đánh dấu, tức là “Bật công cụ gỡ lỗi giao diện người dùng cho XAML” và nhấp vào nút OK.
Bây giờ hãy chạy bất kỳ ứng dụng XAML nào hoặc sử dụng mã XAML sau.
<Window x:Class = "XAMLTestBinding.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>
<ComboBox Name = "comboBox" Margin = "50" Width = "100">
<ComboBoxItem Content = "Green" />
<ComboBoxItem Content = "Yellow" IsSelected = "True" />
<ComboBoxItem Content = "Orange" />
</ComboBox>
<TextBox Name = "textBox" Margin = "50" Width = "100" Height = "23"
VerticalAlignment = "Top" Text =
"{Binding ElementName = comboBox, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}"
Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}">
</TextBox>
</StackPanel>
</Window>
Khi bạn thực thi ứng dụng, nó sẽ hiển thị Cây trực quan nơi tất cả các phần tử được hiển thị trong một cây.
Cây Trực quan Trực tiếp này hiển thị cấu trúc bố cục hoàn chỉnh để hiểu vị trí của các phần tử giao diện người dùng. Nhưng tùy chọn này chỉ khả dụng trong Visual Studio 2015. Nếu bạn đang sử dụng tùy chọn cũ hơn của Visual Studio, thì bạn không thể sử dụng công cụ này, tuy nhiên có một công cụ khác có thể được tích hợp với Visual Studio chẳng hạn như XAML Spy cho Visual Studio . Bạn có thể tải xuống từ xamlspy
Các ứng dụng WPF cho phép tạo các điều khiển tùy chỉnh giúp bạn rất dễ dàng tạo các điều khiển có nhiều tính năng và có thể tùy chỉnh. Các điều khiển tùy chỉnh được sử dụng khi tất cả các điều khiển tích hợp do Microsoft cung cấp không đáp ứng tiêu chí của bạn hoặc bạn không muốn trả tiền cho các điều khiển của bên thứ ba.
Trong chương này, bạn sẽ học cách tạo các điều khiển tùy chỉnh. Trước khi chúng ta bắt đầu xem xét Điều khiển tùy chỉnh, trước tiên chúng ta hãy xem nhanh một Điều khiển người dùng.
Kiểm soát người dùng
Kiểm soát người dùng cung cấp một cách để thu thập và kết hợp các điều khiển tích hợp khác nhau với nhau và đóng gói chúng thành XAML có thể tái sử dụng. Các điều khiển của người dùng được sử dụng trong các trường hợp sau:
Nếu điều khiển bao gồm các điều khiển hiện có, tức là bạn có thể tạo một điều khiển duy nhất gồm nhiều điều khiển đã tồn tại.
Nếu điều khiển không cần hỗ trợ cho chúng. User Controls không hỗ trợ các tùy chỉnh phức tạp, các mẫu điều khiển và khó tạo kiểu.
Nếu một nhà phát triển thích viết các điều khiển bằng cách sử dụng mô hình mã phía sau trong đó một chế độ xem và sau đó là mã trực tiếp phía sau cho trình xử lý sự kiện.
Bạn sẽ không chia sẻ quyền kiểm soát của mình trên các ứng dụng.
Thí dụ
Hãy đi đến ví dụ về Kiểm soát người dùng và làm theo các bước dưới đây.
Tạo một dự án WPF mới và sau đó nhấp chuột phải vào giải pháp của bạn và chọn Thêm> Mục mới ...
Cửa sổ sau sẽ mở ra. Bây giờ chọnUser Control (WPF) và đặt tên là MyUserControl.
Nhấp vào nút Thêm và bạn sẽ thấy rằng hai tệp mới (MyUserControl.xaml và MyUserControl.cs) sẽ được thêm vào giải pháp của bạn.
Đây là mã XAML trong đó một nút và hộp văn bản được tạo với một số thuộc tính trong tệp MyUserControl.xaml.
<UserControl x:Class = "WPFUserControl.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 = "300" d:DesignWidth = "300">
<Grid>
<TextBox Height = "23"
HorizontalAlignment = "Left"
Margin = "80,49,0,0" Name = "txtBox"
VerticalAlignment = "Top" Width = "200" />
<Button Content = "Click Me"
Height = "23" HorizontalAlignment = "Left"
Margin = "96,88,0,0" Name = "button"
VerticalAlignment = "Top" Click = "button_Click" />
</Grid>
</UserControl>
Dưới đây là mã C # cho sự kiện nhấp vào nút trong tệp MyUserControl.cs cập nhật hộp văn bản.
using System;
using System.Windows;
using System.Windows.Controls;
namespace WPFUserControl {
/// <summary>
/// Interaction logic for MyUserControl.xaml
/// </summary>
public partial class MyUserControl : UserControl {
public MyUserControl() {
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e) {
txtBox.Text = "You have just clicked the button";
}
}
}
Đây là cách triển khai trong MainWindow.xaml để thêm quyền kiểm soát của người dùng.
<Window x:Class = "XAMLUserControl.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:control = "clr-namespace:WPFUserControl"
Title = "MainWindow" Height = "350" Width = "525">
<Grid>
<control:MyUserControl/>
</Grid>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau.
Khi nhấp vào nút "Click Me", bạn sẽ nhận thấy rằng văn bản bên trong hộp văn bản được cập nhật.
Kiểm soát tùy chỉnh
Điều khiển tùy chỉnh là một lớp cung cấp kiểu và mẫu riêng của nó thường được định nghĩa trong generic.xaml. Các điều khiển tùy chỉnh được sử dụng trong các trường hợp sau:
Nếu điều khiển không tồn tại và bạn phải tạo nó từ đầu.
Nếu bạn muốn mở rộng hoặc thêm chức năng vào một điều khiển có sẵn bằng cách thêm một thuộc tính bổ sung hoặc một chức năng bổ sung để phù hợp với tình huống cụ thể của bạn.
Nếu điều khiển của bạn cần hỗ trợ chủ đề và kiểu dáng.
Nếu bạn muốn chia sẻ quyền kiểm soát của mình trên các ứng dụng.
Thí dụ
Hãy lấy một ví dụ để hiểu cách điều khiển tùy chỉnh hoạt động. Tạo một dự án WPF mới và sau đó nhấp chuột phải vào giải pháp của bạn và chọn Thêm> Mục mới ...
Nó sẽ mở ra cửa sổ sau. Bây giờ chọnCustom Control (WPF) và đặt tên cho nó MyCustomControl.
Nhấp vào nút Thêm và bạn sẽ thấy rằng hai tệp mới (Themes / Generic.xaml và MyCustomControl.cs) sẽ được thêm vào giải pháp của bạn.
Đây là mã XAML trong đó kiểu được đặt cho điều khiển tùy chỉnh trong tệp Generic.xaml.
<ResourceDictionary
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFCustomControls">
<Style TargetType = "{x:Type local:MyCustomControl}"
BasedOn = "{StaticResource {x:Type Button}}">
<Setter Property = "Background" Value = "LightSalmon" />
<Setter Property = "Foreground" Value = "Blue"/>
</Style>
</ResourceDictionary>
Đây là mã C # cho lớp MyCustomControl được kế thừa từ lớp nút và trong phương thức khởi tạo, nó ghi đè siêu dữ liệu.
using System;
using System.Windows;
using System.Windows.Controls;
namespace WPFCustomControls {
public class MyCustomControl : Button {
static MyCustomControl() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new
FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
}
}
Đây là triển khai sự kiện nhấp chuột điều khiển tùy chỉnh trong C # cập nhật văn bản của khối văn bản.
using System;
using System.Windows;
using System.Windows.Controls;
namespace WPFCustomControls {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void customControl_Click(object sender, RoutedEventArgs e) {
txtBlock.Text = "You have just click your custom control";
}
}
}
Đây là triển khai trong MainWindow.xaml để thêm điều khiển tùy chỉnh và TextBlock.
<Window x:Class = "WPFCustomControls.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:control = "clr-namespace:WPFCustomControls"
Title = "MainWindow" Height = "350" Width = "604">
<StackPanel>
<control:MyCustomControl x:Name = "customControl"
Content = "Click Me" Width = "70"
Margin = "10" Click = "customControl_Click"/>
<TextBlock Name = "txtBlock"
Width = "250" Height = "30"/>
</StackPanel>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau với một điều khiển tùy chỉnh là một nút tùy chỉnh.
Khi nhấp vào nút tùy chỉnh, bạn sẽ thấy văn bản bên trong khối văn bản được cập nhật.
Một ngoại lệ là bất kỳ điều kiện lỗi hoặc một hành vi không mong muốn nào gặp phải trong quá trình thực thi một chương trình. Các ngoại lệ có thể được đưa ra do nhiều lý do, một số trong số đó là như sau:
Lỗi trong mã của bạn hoặc mã mà bạn gọi (chẳng hạn như thư viện được chia sẻ),
Tài nguyên hệ điều hành không khả dụng,
Các điều kiện không mong muốn mà thời gian chạy ngôn ngữ chung gặp phải (chẳng hạn như mã không thể được xác minh)
Cú pháp
Các ngoại lệ có khả năng chuyển luồng chương trình từ phần này sang phần khác. Trong .NET framework, xử lý ngoại lệ có bốn từ khóa sau:
try - Trong khối này, chương trình xác định một điều kiện nhất định làm nảy sinh một số ngoại lệ.
catch- Từ khóa catch cho biết việc bắt một ngoại lệ. Atry khối được theo sau bởi một hoặc nhiều catch khối để bắt một ngoại lệ với một trình xử lý ngoại lệ tại vị trí trong chương trình mà bạn muốn xử lý vấn đề.
finally- Khối cuối cùng được sử dụng để thực thi một tập hợp các câu lệnh đã cho, cho dù một ngoại lệ được ném hay không được ném. Ví dụ: nếu bạn mở một tệp, nó phải được đóng lại cho dù có một ngoại lệ nào được đưa ra hay không.
throw- Một chương trình ném ra một ngoại lệ khi một vấn đề xuất hiện. Điều này được thực hiện bằng cách sử dụng một từ khóa ném.
Cú pháp để sử dụng bốn từ khóa này như sau:
try {
///This will still trigger the exception
}
catch (ExceptionClassName e) {
// error handling code
}
catch (ExceptionClassName e) {
// error handling code
}
catch (ExceptionClassName e) {
// error handling code
}
finally {
// statements to be executed
}
Nhiều câu lệnh bắt được sử dụng trong những trường hợp khối try có thể tạo ra nhiều hơn một ngoại lệ tùy thuộc vào tình huống của dòng chương trình.
Hệ thống cấp bậc
Hầu hết tất cả các lớp ngoại lệ trong .NET framework đều có nguồn gốc trực tiếp hoặc gián tiếp từ lớp Exception. Các lớp ngoại lệ quan trọng nhất bắt nguồn từ lớp Ngoại lệ là:
ApplicationException class- Nó hỗ trợ các trường hợp ngoại lệ do các chương trình tạo ra. Khi nhà phát triển muốn xác định ngoại lệ thì lớp phải được dẫn xuất từ lớp này.
SystemException class- Nó là lớp cơ sở cho tất cả các ngoại lệ của hệ thống thời gian chạy được xác định trước. Hệ thống phân cấp sau đây cho thấy các ngoại lệ tiêu chuẩn được cung cấp bởi thời gian chạy.
Bảng sau liệt kê các ngoại lệ tiêu chuẩn được cung cấp bởi thời gian chạy và các điều kiện mà bạn nên tạo một lớp dẫn xuất.
Loại ngoại lệ | Loại cơ sở | Sự miêu tả |
---|---|---|
Exception | Vật | Lớp cơ sở cho tất cả các trường hợp ngoại lệ. |
SystemException | ngoại lệ | Lớp cơ sở cho tất cả các lỗi do thời gian chạy tạo ra. |
IndexOutOfRangeException | SystemException | Bị ném bởi thời gian chạy chỉ khi một mảng được lập chỉ mục không đúng cách. |
NullReferenceException | SystemException | Bị ném bởi thời gian chạy chỉ khi một đối tượng rỗng được tham chiếu. |
AccessViolationException | SystemException | Bị ném bởi thời gian chạy chỉ khi bộ nhớ không hợp lệ được truy cập. |
InvalidOperationException | SystemException | Ném bằng các phương thức khi ở trạng thái không hợp lệ. |
ArgumentException | SystemException | Lớp cơ sở cho tất cả các ngoại lệ đối số. |
ArgumentNullException | ArgumentException | Bị ném bởi các phương thức không cho phép một đối số là giá trị rỗng. |
ArgumentOutOfRangeException | ArgumentException | Đưa ra bởi các phương pháp xác minh rằng các đối số nằm trong một phạm vi nhất định. |
ExternalException | SystemException | Lớp cơ sở cho các ngoại lệ xảy ra hoặc được nhắm mục tiêu vào các môi trường bên ngoài thời gian chạy. |
SEHException | Trường hợp ngoại lệ | Ngoại lệ đóng gói thông tin xử lý ngoại lệ có cấu trúc Win32. |
Thí dụ
Hãy lấy một ví dụ đơn giản để hiểu khái niệm này tốt hơn. Bắt đầu bằng cách tạo một dự án WPF mới với tênWPFExceptionHandling.
Kéo một hộp văn bản từ hộp công cụ vào cửa sổ thiết kế. Mã XAML sau đây tạo một hộp văn bản và khởi tạo nó với một số thuộc tính.
<Window x:Class = "WPFExceptionHandling.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFExceptionHandling"
mc:Ignorable = "d"
Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<TextBox x:Name = "textBox" HorizontalAlignment = "Left"
Height = "241" Margin = "70,39,0,0" TextWrapping = "Wrap"
VerticalAlignment = "Top" Width = "453"/>
</Grid>
</Window>
Đây là cách đọc tệp có xử lý ngoại lệ trong C #.
using System;
using System.IO;
using System.Windows;
namespace WPFExceptionHandling {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
ReadFile(0);
}
void ReadFile(int index) {
string path = @"D:\Test.txt";
StreamReader file = new StreamReader(path);
char[] buffer = new char[80];
try {
file.ReadBlock(buffer, index, buffer.Length);
string str = new string(buffer);
str.Trim();
textBox.Text = str;
}
catch (Exception e) {
MessageBox.Show("Error reading from "+ path + "\nMessage = "+ e.Message);
}
finally {
if (file != null) {
file.Close();
}
}
}
}
}
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau, trong đó văn bản được hiển thị bên trong hộp văn bản.
Khi có một ngoại lệ được nâng lên hoặc bạn ném nó theo cách thủ công (như trong đoạn mã sau), thì nó sẽ hiển thị một hộp thông báo có lỗi.
using System;
using System.IO;
using System.Windows;
namespace WPFExceptionHandling {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
ReadFile(0);
}
void ReadFile(int index) {
string path = @"D:\Test.txt";
StreamReader file = new StreamReader(path);
char[] buffer = new char[80];
try {
file.ReadBlock(buffer, index, buffer.Length);
string str = new string(buffer);
throw new Exception();
str.Trim();
textBox.Text = str;
}
catch (Exception e) {
MessageBox.Show("Error reading from "+ path + "\nMessage = "+ e.Message);
}
finally {
if (file != null) {
file.Close();
}
}
}
}
}
Khi một ngoại lệ được đưa ra trong khi thực thi đoạn mã trên, nó sẽ hiển thị thông báo sau.
Chúng tôi khuyên bạn nên thực thi mã trên và thử nghiệm với các tính năng của nó.
Bản địa hóa là việc dịch các tài nguyên ứng dụng thành các phiên bản được bản địa hóa cho các nền văn hóa cụ thể mà ứng dụng hỗ trợ.
Khi bạn phát triển ứng dụng của mình và ứng dụng của bạn chỉ có sẵn bằng một ngôn ngữ, thì bạn đang giới hạn số lượng khách hàng và quy mô doanh nghiệp của mình. Nếu bạn muốn tăng cơ sở khách hàng, điều này cũng sẽ làm tăng doanh nghiệp của bạn, thì sản phẩm của bạn phải có sẵn và có thể tiếp cận được với khán giả toàn cầu. Tiết kiệm chi phílocalization sản phẩm của bạn là một trong những cách tốt nhất và tiết kiệm nhất để tiếp cận với nhiều khách hàng hơn.
Trong WPF, các ứng dụng có thể bản địa hóa rất dễ tạo với resxđó là giải pháp đơn giản nhất để bản địa hóa. Hãy lấy một ví dụ đơn giản để hiểu cách nó hoạt động -
Tạo một dự án WPF mới với tên WPFLocalization.
Trong trình khám phá giải pháp của mình, bạn sẽ thấy tệp Resources.resx trong thư mục Thuộc tính.
Thay đổi công cụ sửa đổi quyền truy cập từ nội bộ thành công khai để nó có thể truy cập được trong tệp XAML.
Bây giờ, hãy thêm tên và các giá trị của chuỗi sau mà chúng ta sẽ sử dụng trong ứng dụng của mình.
Tạo hai bản sao của tệp Resources.resx với các tên Resources.en.resx và Resources.ru-RU.resx. Đây là các quy ước đặt tên cụ thể cho ngôn ngữ và tên quốc gia / khu vực và có thể tìm thấy nó trên Tham chiếu API hỗ trợ ngôn ngữ quốc gia (NLS) (https://msdn.microsoft.com/en-us/goglobal/bb896001.aspx ) trang.
Thay đổi các giá trị trong Resources.ru-RU.resx thành các từ tiếng Nga, như được hiển thị bên dưới.
Hãy vào cửa sổ thiết kế và kéo ba hộp văn bản, ba nhãn và ba nút.
Trong tệp XAML, trước tiên hãy thêm khai báo không gian tên để sử dụng bản địa hóa tài nguyên xmlns: p = "clr-namespace: WPFLocalization.Properties"
Đặt thuộc tính của tất cả các điều khiển như hình dưới đây. Trong ví dụ này, chúng tôi sẽ không sử dụng các chuỗi mã cứng cho nội dung của nhãn, nút và Tiêu đề của cửa sổ trong tệp XAML. Chúng tôi sẽ sử dụng các chuỗi được xác định trong các tệp * .resx. Ví dụ: đối với Tiêu đề của cửa sổ, chúng tôi sử dụng chuỗi Tiêu đề được xác định trong tệp * .resx như sau “Title =" {x: Static p: Resources.Title} ""
Đây là tệp XAML trong đó các điều khiển được tạo và khởi tạo với các thuộc tính khác nhau.
<Window x:Class = "WPFLocalization.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local = "clr-namespace:WPFLocalization"
xmlns:p = "clr-namespace:WPFLocalization.Properties"
Title = "{x:Static p:Resources.Title}" Height = "350" Width = "604">
<Grid>
<TextBox x:Name = "textBox" HorizontalAlignment = "Left" Height = "23"
Margin = "128,45,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "304"/>
<Label x:Name = "label" Content = "{x:Static p:Resources.Name}"
HorizontalAlignment = "Left" Margin = "52,45,0,0" VerticalAlignment = "Top" Width = "86"/>
<TextBox x:Name = "textBox1" HorizontalAlignment = "Left" Height = "23"
Margin = "128,102,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "304"/>
<Label x:Name = "label1" Content = "{x:Static p:Resources.Address}"
HorizontalAlignment = "Left" Margin = "52,102,0,0" VerticalAlignment = "Top" Width = "86"/>
<TextBox x:Name = "textBox2" HorizontalAlignment = "Left" Height = "23"
Margin = "128,157,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "80"/>
<Label x:Name = "label2" Content = "{x:Static p:Resources.Age}"
HorizontalAlignment = "Left" Margin = "52,157,0,0" VerticalAlignment = "Top" Width = "86"/>
<Button x:Name = "button" Content = "{x:Static p:Resources.OK_Button}"
HorizontalAlignment = "Left" Margin = "163,241,0,0" VerticalAlignment = "Top" Width = "75"/>
<Button x:Name = "button1" Content = "{x:Static p:Resources.Cancel_Button}"
HorizontalAlignment = "Left" Margin = "282,241,0,0" VerticalAlignment = "Top" Width = "75"/>
<Button x:Name = "button2" Content = "{x:Static p:Resources.Help_Button}"
HorizontalAlignment = "Left" Margin = "392,241,0,0" VerticalAlignment = "Top" Width = "75"/>
</Grid>
</Window>
Khi đoạn mã trên được biên dịch và thực thi, bạn sẽ thấy cửa sổ sau chứa các điều khiển khác nhau.
Theo mặc định, chương trình sử dụng Resources.resx mặc định. Nếu bạn muốn hiển thị văn bản bằng tiếng Nga được xác định trong tệp Resources.ru-RU.resx, thì bạn sẽ cần đặt văn hóa rõ ràng khi chương trình khởi động trong tệp App.xaml như hình dưới đây.
using System.Windows;
namespace WPFLocalization {
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application {
App() {
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("ru-RU");
//System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
}
}
}
Khi bạn chạy ứng dụng của mình, bạn sẽ thấy tất cả văn bản bằng tiếng Nga.
Chúng tôi khuyên bạn nên thực thi mã trên và tạo tệp resx cho các nền văn hóa khác.
Trong WPF, một tương tác cho biết cách một chế độ xem tương tác với các điều khiển nằm trong chế độ xem đó. Các tương tác phổ biến nhất được biết đến có hai loại:
- Behaviors
- Kéo và thả
Hành vi cư xử
Behaviors được giới thiệu với Expression Blend 3 có thể đóng gói một số chức năng vào một thành phần có thể tái sử dụng. Để thêm các hành vi bổ sung, bạn có thể đính kèm các thành phần này vào các điều khiển. Các hành vi cung cấp tính linh hoạt hơn để dễ dàng thiết kế các tương tác phức tạp của người dùng.
Hãy xem một ví dụ đơn giản trong đó hành vi ControlStoryBoardAction được gắn vào các điều khiển.
Tạo một dự án WPF mới với tên WPFBehavior.
Đoạn mã XAML sau đây tạo một hình elip và hai nút để điều khiển chuyển động của hình elip.
<Window
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFBehaviors"
xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei = "http://schemas.microsoft.com/expression/2010/interactions"
x:Class = "WPFBehaviors.MainWindow"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Window.Resources>
<Storyboard x:Key = "Storyboard1" RepeatBehavior = "Forever" AutoReverse = "True">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
"(UIElement.RenderTransform).(TransformGroup.Children )[3].(TranslateTransform.X)"
Storyboard.TargetName = "ellipse">
<EasingDoubleKeyFrame KeyTime = "0:0:1" Value = "301.524"/>
<EasingDoubleKeyFrame KeyTime = "0:0:2" Value = "2.909"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
"(UIElement.RenderTransform).(TransformGroup.Children )[3].(TranslateTransform.Y)"
Storyboard.TargetName = "ellipse">
<EasingDoubleKeyFrame KeyTime = "0:0:1" Value = "-0.485"/>
<EasingDoubleKeyFrame KeyTime = "0:0:2" Value = "0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty = "(ContentControl.Content)"
Storyboard.TargetName = "button">
<DiscreteObjectKeyFrame KeyTime = "0" Value = "Play"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty = "(ContentControl.Content)"
Storyboard.TargetName = "button1">
<DiscreteObjectKeyFrame KeyTime = "0" Value = "Stop"/>
<DiscreteObjectKeyFrame KeyTime = "0:0:2" Value = "Stop"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent = "FrameworkElement.Loaded">
<BeginStoryboard Storyboard = "{StaticResource Storyboard1}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Ellipse x:Name = "ellipse" Fill = "#FFAAAAC5" HorizontalAlignment = "Left"
Height = "50.901" Margin = "49.324,70.922,0,0" Stroke = "Black"
VerticalAlignment = "Top" Width = "73.684" RenderTransformOrigin = "0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>
<Button x:Name = "button" Content = "Play" HorizontalAlignment = "Left" Height = "24.238"
Margin = "63.867,0,0,92.953" VerticalAlignment = "Bottom" Width = "74.654">
<i:Interaction.Triggers>
<i:EventTrigger EventName = "Click">
<ei:ControlStoryboardAction Storyboard = "{StaticResource Storyboard1}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button x:Name = "button1" Content = "Stop" HorizontalAlignment = "Left" Height = "24.239"
Margin = "160.82,0,0,93.922" VerticalAlignment = "Bottom" Width = "75.138">
<i:Interaction.Triggers>
<i:EventTrigger EventName = "Click">
<ei:ControlStoryboardAction ControlStoryboardOption = "Stop"
Storyboard = "{StaticResource Storyboard1}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau chứa một hình elip và hai nút.
Khi bạn nhấn nút phát, nó sẽ bắt đầu di chuyển từ trái sang phải và sau đó sẽ quay trở lại vị trí ban đầu. Nút dừng sẽ dừng chuyển động của hình elip.
Kéo và thả
Kéo và thả trên giao diện người dùng có thể nâng cao đáng kể hiệu quả và năng suất của ứng dụng. Có rất ít ứng dụng sử dụng tính năng kéo và thả vì mọi người nghĩ rằng nó khó thực hiện. Ở một mức độ nào đó, rất khó để xử lý một tính năng kéo và thả, nhưng trong WPF, bạn có thể xử lý nó khá dễ dàng.
Hãy lấy một ví dụ đơn giản để hiểu nó hoạt động như thế nào. Chúng tôi sẽ tạo một ứng dụng trong đó bạn có thể kéo và thả màu từ hình chữ nhật này sang hình chữ nhật khác.
Tạo một dự án WPF mới với tên WPFDragAndDrop.
Kéo năm hình chữ nhật vào cửa sổ thiết kế và đặt các thuộc tính như được hiển thị trong tệp XAML sau đây.
<Window x:Class = "WPFDragAndDrop.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFDragAndDrop"
mc:Ignorable = "d" Title = "MainWindow" Height = "402.551" Width = "604">
<Grid>
<Rectangle Name = "Target" Fill = "AliceBlue" HorizontalAlignment = "Left"
Height = "345" Margin = "10,10,0,0" Stroke = "Black"
VerticalAlignment = "Top" Width = "387" AllowDrop = "True" Drop = "Target_Drop"/>
<Rectangle Fill = "Beige" HorizontalAlignment = "Left" Height = "65"
Margin = "402,10,0,0" Stroke = "Black" VerticalAlignment = "Top"
Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>
<Rectangle Fill = "LightBlue" HorizontalAlignment = "Left" Height = "65"
Margin = "402,80,0,0" Stroke = "Black" VerticalAlignment = "Top"
Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>
<Rectangle Fill = "LightCoral" HorizontalAlignment = "Left" Height = "65"
Margin = "402,150,0,0" Stroke = "Black" VerticalAlignment = "Top"
Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>
<Rectangle Fill = "LightGray" HorizontalAlignment = "Left" Height = "65"
Margin = "402,220,0,0" Stroke = "Black" VerticalAlignment = "Top"
Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>
<Rectangle Fill = "OliveDrab" HorizontalAlignment = "Left" Height = "65"
Margin = "402,290,0,-7" Stroke = "Black" VerticalAlignment = "Top"
Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>
</Grid>
</Window>
Hình chữ nhật đầu tiên là hình chữ nhật mục tiêu, vì vậy người dùng có thể kéo màu từ hình chữ nhật khác sang hình chữ nhật mục tiêu.
Dưới đây là các sự kiện triển khai trong C # để kéo và thả.
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WPFDragAndDrop {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Rect_MLButtonDown(object sender, MouseButtonEventArgs e) {
Rectangle rc = sender as Rectangle;
DataObject data = new DataObject(rc.Fill);
DragDrop.DoDragDrop(rc, data,DragDropEffects.Move);
}
private void Target_Drop(object sender, DragEventArgs e) {
SolidColorBrush scb = (SolidColorBrush)e.Data.GetData(typeof(SolidColorBrush));
Target.Fill = scb;
}
}
}
Khi bạn chạy ứng dụng của mình, nó sẽ tạo ra cửa sổ sau.
Nếu bạn kéo một màu từ hình chữ nhật ở phía bên phải và thả nó vào hình chữ nhật lớn bên trái, bạn sẽ thấy hiệu ứng của nó ngay lập tức.
Hãy kéo cái thứ 4 từ phía bên phải.
Bạn có thể thấy rằng màu của hình chữ nhật mục tiêu đã thay đổi. Chúng tôi khuyên bạn nên thực thi mã trên và thử nghiệm với các tính năng của nó.
WPF cung cấp nhiều loại đồ họa 2D có thể được nâng cao theo yêu cầu ứng dụng của bạn. WPF hỗ trợ cả các đối tượng Drawing và Shape được sử dụng để vẽ nội dung đồ họa.
Hình dạng và Bản vẽ
Lớp Shape có nguồn gốc từ lớp FrameworkElement, các đối tượng Shape có thể được sử dụng bên trong các bảng điều khiển và hầu hết các điều khiển.
WPF cung cấp một số đối tượng hình dạng cơ bản có nguồn gốc từ lớp Hình dạng như Ellipse, Line, Path, Polygon, Polyline và Rectangle.
Mặt khác, các đối tượng vẽ không bắt nguồn từ lớp FrameworkElement và cung cấp một triển khai nhẹ hơn.
Đối tượng vẽ đơn giản hơn so với đối tượng Shape. Chúng cũng có đặc điểm hiệu suất tốt hơn.
Thí dụ
Hãy lấy một ví dụ đơn giản để hiểu cách sử dụng các đối tượng hình dạng khác nhau.
Tạo một dự án WPF mới với tên WPF2DGraphics.
Đoạn mã sau đây tạo ra các loại hình dạng khác nhau.
<Window x:Class = "WPF2DGraphics.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPF2DGraphics"
xmlns:PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/present ation/options"
mc:Ignorable = "PresentationOptions" Title = "MainWindow" Height = "400" Width = "604">
<StackPanel>
<Ellipse Width = "100" Height = "60" Name = "sample" Margin = "10">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Offset = "0" Color = "AliceBlue"/>
<GradientStop Offset = "1" Color = "Gray"/>
<GradientStop Offset = "2" Color = "Red"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Path Stroke = "Red" StrokeThickness = "5" Data = "M 10,70 L 200,70"
Height = "42.085" Stretch = "Fill" Margin = "140.598,0,146.581,0" />
<Path Stroke = "BlueViolet" StrokeThickness = "5" Data = "M 20,100 A 100,56 42 1 0 200,10"
Height = "81.316" Stretch = "Fill" Margin = "236.325,0,211.396,0" />
<Path Fill = "LightCoral" Margin = "201.424,0,236.325,0"
Stretch = "Fill" Height = "124.929">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint = "50,0" IsClosed = "True">
<LineSegment Point = "100,50"/>
<LineSegment Point = "50,100"/>
<LineSegment Point = "0,50"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</StackPanel>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra một hình elip, một đường thẳng, một cung và một đa giác.
Thí dụ
Hãy xem một ví dụ khác cho thấy cách vẽ một khu vực bằng hình vẽ.
Tạo một dự án WPF mới với tên WPF2DGraphics1.
Đoạn mã XAML sau đây cho thấy cách vẽ khác với vẽ hình ảnh.
<Window x:Class = "WPF2DGraphics1.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/present ation/options"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable = "PresentationOptions"
xmlns:local = "clr-namespace:WPF2DGraphics1" Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<Border BorderBrush = "Gray" BorderThickness = "1"
HorizontalAlignment = "Left" VerticalAlignment = "Top"
Margin = "20">
<Image Stretch = "None">
<Image.Source>
<DrawingImage PresentationOptions:Freeze = "True">
<DrawingImage.Drawing>
<DrawingGroup>
<ImageDrawing Rect = "300,100,300,180" ImageSource = "Images\DSC_0104.JPG"/>
<ImageDrawing Rect = "0,100,250,100" ImageSource = "Images\DSC_0104.JPG"/>
<ImageDrawing Rect = "150,0,25,25" ImageSource = "Images\DSC_0104.JPG"/>
<ImageDrawing Rect = "0,0,75,75" ImageSource = "Images\DSC_0104.JPG"/>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>
</Grid>
</Window>
Khi bạn chạy ứng dụng của mình, nó sẽ tạo ra kết quả sau:
Chúng tôi khuyên bạn nên thực thi mã trên và thử thêm các hình dạng và bản vẽ 2D.
Windows Presentation Foundation (WPF) cung cấp một chức năng để vẽ, chuyển đổi và tạo hoạt ảnh cho đồ họa 3D theo yêu cầu ứng dụng của bạn. Nó không hỗ trợ phát triển trò chơi 3D hoàn chỉnh, nhưng ở một mức độ nào đó, bạn có thể tạo đồ họa 3D.
Bằng cách kết hợp đồ họa 2D và 3D, bạn cũng có thể tạo các điều khiển phong phú, cung cấp các hình ảnh minh họa phức tạp về dữ liệu hoặc nâng cao trải nghiệm người dùng về giao diện của ứng dụng. Phần tử Viewport3D lưu trữ mô hình 3D vào ứng dụng WPF của chúng tôi.
Thí dụ
Hãy lấy một ví dụ đơn giản để hiểu cách sử dụng đồ họa 3D.
Tạo một dự án WPF mới với tên WPF3DGraphics.
Mã XAML sau đây cho thấy cách tạo một đối tượng 2D bằng hình học 3D.
<Window x:Class = "WPF3DGraphics.MainWindow"
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:local = "clr-namespace:WPF3DGraphics"
mc:Ignorable = "d" Title = "MainWindow" Height = "500" Width = "604">
<Grid>
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera Position = "2,0,10" LookDirection = "0.2,0.4,-1"
FieldOfView = "65" UpDirection = "0,1,0" />
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<AmbientLight Color = "Bisque" />
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D Positions = "0,0,0 0,8,0 10,0,0 8,8,0"
Normals = "0,0,1 0,0,1 0,0,1 0,0,1" TriangleIndices = "0,2,1 1,2,3"/>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial Brush = "Bisque" />
</GeometryModel3D.Material>
</GeometryModel3D>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D>
</Grid>
</Window>
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra một đối tượng 2D ở dạng 3D.
Thí dụ
Hãy xem một ví dụ khác cho thấy một vật thể 3D.
Tạo một dự án WPF mới với tên WPF3DGraphics1
Mã XAML sau đây tạo một đối tượng 3D và một thanh trượt. Với sự trợ giúp của thanh trượt, bạn có thể xoay đối tượng 3D này.
<Window x:Class = "WPF3DGraphics1.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPF3DGraphics1"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525">
<Grid>
<Viewport3D Name="viewport3D1">
<Viewport3D.Camera>
<PerspectiveCamera x:Name = "camMain" Position = "6 5 4" LookDirection = "-6 -5 -4">
</PerspectiveCamera>
</Viewport3D.Camera>
<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight x:Name = "dirLightMain" Direction = "-1,-1,-1">
</DirectionalLight>
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D x:Name = "MyModel">
<ModelVisual3D.Content>
<GeometryModel3D>
<GeometryModel3D.Geometry>
<MeshGeometry3D x:Name = "meshMain"
Positions = "0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 1 0 1 1 0 1 1"
TriangleIndices = "2 3 1 3 1 0 7 1 3 7 5 1 6 5 7 6 4 5 6 2 0
2 0 4 2 7 3 2 6 7 0 1 5 0 5 4">
</MeshGeometry3D>
</GeometryModel3D.Geometry>
<GeometryModel3D.Material>
<DiffuseMaterial x:Name = "matDiffuseMain">
<DiffuseMaterial.Brush>
<SolidColorBrush Color = "Bisque"/>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
</GeometryModel3D>
</ModelVisual3D.Content>
<ModelVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name = "rotate" Axis = "1 2 1"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
</ModelVisual3D.Transform>
</ModelVisual3D>
</Viewport3D>
<Slider Height = "23" HorizontalAlignment = "Left"
Margin = "145,271,0,0" Name = "slider1"
VerticalAlignment = "Top" Width = "269"
Maximum = "360"
Value = "{Binding ElementName = rotate, Path=Angle}" />
</Grid>
</Window>
Khi bạn chạy ứng dụng của mình, nó sẽ tạo ra một đối tượng 3D và một thanh trượt trên cửa sổ của bạn.
Khi bạn trượt thanh trượt, đối tượng trên cửa sổ của bạn cũng sẽ xoay.
Chúng tôi khuyên bạn nên thực thi mã trên và thử thêm hình học 3D.
Ứng dụng WPF hỗ trợ sử dụng video và âm thanh MediaElement. Nó cho phép bạn tích hợp âm thanh và video vào một ứng dụng. Lớp MediaElement hoạt động theo cách tương tự như lớp Image. Bạn chỉ cần trỏ nó vào phương tiện truyền thông và nó hiển thị nó. Sự khác biệt chính là nó sẽ là một hình ảnh chuyển động, nhưng nếu bạn trỏ nó vào tệp chỉ chứa âm thanh và không có video như MP3, nó sẽ phát mà không hiển thị bất kỳ thứ gì trên màn hình.
WPF hỗ trợ tất cả các loại định dạng video / âm thanh tùy theo cấu hình máy. Nếu tệp phương tiện phát Media Player, nó cũng sẽ hoạt động trong WPF trên cùng một máy.
Thí dụ
Hãy lấy một ví dụ để hiểu cách tích hợp đa phương tiện trong ứng dụng của bạn.
Tạo một dự án WPF mới với tên WPFMultimedia.
Mã XAML sau đây tạo một phần tử media và ba nút, và khởi tạo chúng với một số thuộc tính.
<Window x:Class = "WPFMultimedia.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFMultimedia"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<StackPanel HorizontalAlignment = "Center" VerticalAlignment = "Center">
<MediaElement Name = "myMedia" Source = "D:\MicrosoftMVA.mp4"
LoadedBehavior = "Manual" Width = "591" Height = "274" />
<StackPanel Orientation = "Horizontal" Margin = "0,10,0,0">
<Button Content = "Play" Margin = "0,0,10,0" Padding = "5" Click = "mediaPlay" />
<Button Content = "Pause" Margin = "0,0,10,0" Padding = "5" Click = "mediaPause" />
<Button x:Name = "muteButt" Content = "Mute" Padding = "5" Click = "mediaMute" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
Đây là triển khai sự kiện Click trong C # cho các nút khác nhau.
using System;
using System.Windows;
namespace WPFMultimedia {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
myMedia.Volume = 100;
myMedia.Play();
}
void mediaPlay(Object sender, EventArgs e) {
myMedia.Play();
}
void mediaPause(Object sender, EventArgs e) {
myMedia.Pause();
}
void mediaMute(Object sender, EventArgs e) {
if (myMedia.Volume == 100) {
myMedia.Volume = 0;
muteButt.Content = "Listen";
}
else {
myMedia.Volume = 100;
muteButt.Content = "Mute";
}
}
}
}
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau. Bạn có thể phát video và điều khiển việc phát lại video bằng ba nút.
Với các nút, bạn có thể tạm dừng, tắt tiếng và phát video.
Bộ tổng hợp giọng nói
WPF có các tính năng chuyển văn bản thành giọng nói. API này được bao gồm trong không gian tên System.Speech.SpeechSynthesizer lớp chuyển văn bản thành lời nói.
Thí dụ
Hãy xem một ví dụ đơn giản.
Tạo một dự án WPF mới với tên WPFTextToSpeech.
Chúng tôi sẽ cần lắp ráp System.Speech để thêm làm tài liệu tham khảo cho SpeechSynthesizer lớp để làm việc.
Nhấp chuột phải vào Tài liệu tham khảo và chọn Thêm tài liệu tham khảo.
Hộp thoại Trình quản lý tham chiếu sẽ mở ra. Bây giờ hãy chọn hộp kiểm System.Speech
Nhấp vào nút Ok. Bạn có thể thấy cụm System.Speech trong Tài liệu tham khảo của mình.
Bây giờ kéo một nút và một hộp văn bản vào cửa sổ thiết kế từ hộp công cụ.
Mã XAML sau đây tạo một nút và một hộp văn bản, đồng thời khởi tạo chúng với một số thuộc tính.
<Window x:Class = "WPFTextToSpeech.MainWindow"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local = "clr-namespace:WPFTextToSpeech"
mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
<Grid>
<Button x:Name = "button" Content = "Speak"
HorizontalAlignment = "Left" Margin = "218,176,0,0"
VerticalAlignment = "Top" Width = "75"/>
<TextBox x:Name = "textBox" HorizontalAlignment = "Left"
Height = "23" Margin = "60,104,0,0" TextWrapping = "Wrap"
VerticalAlignment = "Top" Width = "418"/>
</Grid>
</Window>
Đây là cách triển khai đơn giản trong C # sẽ chuyển Văn bản bên trong hộp văn bản thành lời nói.
using System.Speech.Synthesis;
using System.Windows;
namespace WPFTextToSpeech {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e) {
if (textBox.Text != "") {
SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer();
speechSynthesizer.Speak(textBox.Text);
}
else {
MessageBox.Show("Write some thing in the textbox!");
}
}
}
}
Khi bạn biên dịch và thực thi đoạn mã trên, nó sẽ tạo ra cửa sổ sau. Bây giờ, gõ Hello World bên trong hộp văn bản và nhấp vào nút Nói.
Nó sẽ tạo ra âm thanh "Hello World". Nếu bạn không nhập bất cứ thứ gì vào hộp văn bản, thì nó sẽ nhấp nháy thông báo sau.
Chúng tôi khuyên bạn nên thực hiện các ví dụ trên.