This article has been localized into Vietnamese by the community.
Tạo hộp thoại nhập tùy chỉnh
Trong vài bài viết trước, chúng tôi đã xem xét việc sử dụng các hộp thoại tích hợp của WPF, nhưng việc tạo riêng của bạn gần như dễ dàng. Trong thực tế, bạn thực sự chỉ cần tạo một Cửa sổ, đặt các điều khiển cần thiết vào đó và sau đó hiển thị nó.
Tuy nhiên, có một vài điều bạn cần lưu ý khi tạo hộp thoại, để đảm bảo ứng dụng của bạn hoạt động như các ứng dụng Windows khác. Trong bài viết này, chúng ta sẽ tạo một hộp thoại đơn giản, để hỏi người dùng một câu hỏi và sau đó đưa ra câu trả lời, trong khi thảo luận về một vài thói quen lập trình mà bạn nên tuân theo.
Thiết kế hộp thoại
Đối với hộp thoại cụ thể này, tôi chỉ muốn một Label cho người dùng biết thông tin chúng tôi cần từ anh ấy/cô ấy, một TextBox để nhập câu trả lời, sau đó là các nút Ok và Cancel thông thường. Tôi quyết định thêm một icon vào hộp thoại, để cho đẹp. Đây là kết quả cuối cùng:
Và đây là code cho hộp thoại:
<Window x:Class="WpfTutorialSamples.Dialogs.InputDialogSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Input" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen"
ContentRendered="Window_ContentRendered">
<Grid Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="/WpfTutorialSamples;component/Images/question32.png" Width="32" Height="32" Grid.RowSpan="2" Margin="20,0" />
<Label Name="lblQuestion" Grid.Column="1">Question:</Label>
<TextBox Name="txtAnswer" Grid.Column="1" Grid.Row="1" MinWidth="250">Answer</TextBox>
<WrapPanel Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="0,15,0,0">
<Button IsDefault="True" Name="btnDialogOk" Click="btnDialogOk_Click" MinWidth="60" Margin="0,0,10,0">_Ok</Button>
<Button IsCancel="True" MinWidth="60">_Cancel</Button>
</WrapPanel>
</Grid>
</Window>
using System;
using System.Windows;
namespace WpfTutorialSamples.Dialogs
{
public partial class InputDialogSample : Window
{
public InputDialogSample(string question, string defaultAnswer = "")
{
InitializeComponent();
lblQuestion.Content = question;
txtAnswer.Text = defaultAnswer;
}
private void btnDialogOk_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void Window_ContentRendered(object sender, EventArgs e)
{
txtAnswer.SelectAll();
txtAnswer.Focus();
}
public string Answer
{
get { return txtAnswer.Text; }
}
}
}
Mã này khá đơn giản, nhưng đây là những điều mà bạn nên đặc biệt chú ý:
XAML
Trong phần XAML, tôi đã sử dụng Grid để bố trí các điều khiển - không có gì lạ mắt ở đây. Tôi đã xóa các thuộc tính Chiều rộng và Chiều cao của Cửa sổ và thay vào đó, đặt nó tự động thay đổi kích thước để phù hợp với nội dung - điều này có ý nghĩa trong một hộp thoại, vì vậy bạn không phải tinh chỉnh kích thước để mọi thứ trông ổn. Thay vào đó, hãy sử dụng lề và kích thước tối thiểu để đảm bảo mọi thứ trông giống như bạn muốn, trong khi vẫn cho phép người dùng thay đổi kích thước hộp thoại.
Một thuộc tính khác mà tôi đã thay đổi trên Window là thuộc tính WindowStartupLocation. Đối với một hộp thoại như thế này và có lẽ đối với hầu hết các cửa sổ không chính khác, bạn nên thay đổi giá trị này thành CenterScreen hoặc CenterOwner, để thay đổi hành vi mặc định nơi cửa sổ của bạn sẽ xuất hiện ở vị trí do Windows quyết định, trừ khi bạn chỉ định thủ công Top và Left tài sản cho nó.
Cũng đặc biệt chú ý đến hai thuộc tính tôi đã sử dụng trên các nút hộp thoại: IsCancel và IsDefault. IsCancel nói với WPF rằng nếu người dùng nhấp vào nút này, DialogResult của Window sẽ được đặt thành false, điều này cũng sẽ đóng window. Điều này cũng đảm bảo rằng người dùng có thể nhấn phím Esc trên bàn phím của họ để đóng window, một điều luôn luôn có thể có trong hộp thoại Windows.
Thuộc tính IsDefault tập trung vào nút Ok và cũng đảm bảo rằng nếu người dùng nhấn phím Enter trên bàn phím của họ, nút này được kích hoạt. Một trình xử lý sự kiện là cần thiết để thiết lập DialogResult cho điều này, như được mô tả sau.
Code-behind
Trong Code-behind, tôi đã thay đổi hàm tạo để lấy hai tham số, với một tham số là tùy chọn. Điều này cho phép chúng tôi đặt câu hỏi và câu trả lời mặc định, nếu được cung cấp, vào các điều khiển UI được chỉ định.
Nút Ok có trình xử lý sự kiện đảm bảo rằng thuộc tính DialogResult đặc biệt của Window được đặt thành true khi nhấp, để báo hiệu cho người khởi tạo hộp thoại rằng người dùng chấp nhận giá trị đã nhập. Chúng tôi không có nút nào cho nút Hủy vì WPF xử lý việc này cho chúng tôi khi chúng tôi đặt thuộc tính IsCancel thành true, như được mô tả ở trên.
Để tập trung vào TextBox khi hiển thị hộp thoại, tôi đã đăng ký sự kiện ContentRendered, nơi tôi chọn tất cả văn bản trong điều khiển và sau đó focus nó. Nếu tôi chỉ muốn focus, tôi có thể sử dụng thuộc tính được đính kèm FocusManager.FocusedElement trên Window, nhưng trong trường hợp này, tôi cũng muốn chọn văn bản, để cho phép người dùng ghi đè ngay câu trả lời được cung cấp theo mặc định (nếu có ).
Một chi tiết cuối cùng là thuộc tính Answer mà tôi đã triển khai. Nó chỉ đơn giản cung cấp quyền truy cập vào giá trị đã nhập của điều khiển TextBox, nhưng cách tốt nhất là cung cấp một thuộc tính với (các) giá trị trả về của hộp thoại, thay vì truy cập trực tiếp các điều khiển từ bên ngoài cửa sổ. Điều này cũng cho phép bạn ảnh hưởng đến giá trị trả về trước khi trả lại, nếu cần.
Sử dụng hộp thoại
Với tất cả những điều trên, chúng ta hiện đã sẵn sàng để sử dụng hộp thoại của chúng ta. Đó là một nhiệm vụ rất đơn giản, vì vậy tôi đã tạo ra một ứng dụng nhỏ để thử nghiệm nó. Đây là code:
<Window x:Class="WpfTutorialSamples.Dialogs.InputDialogAppSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="InputDialogAppSample" Height="150" Width="300">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock>Hello, world. My name is:</TextBlock>
<TextBlock Name="lblName" Margin="0,10" TextAlignment="Center" FontWeight="Bold">[No name entered]</TextBlock>
<Button Name="btnEnterName" Click="btnEnterName_Click">Enter name...</Button>
</StackPanel>
</Window>
using System;
using System.Windows;
namespace WpfTutorialSamples.Dialogs
{
public partial class InputDialogAppSample : Window
{
public InputDialogAppSample()
{
InitializeComponent();
}
private void btnEnterName_Click(object sender, RoutedEventArgs e)
{
InputDialogSample inputDialog = new InputDialogSample("Please enter your name:", "John Doe");
if(inputDialog.ShowDialog() == true)
lblName.Text = inputDialog.Answer;
}
}
}
Không có gì đặc biệt với nó - chỉ có một vài điều khiển TextBlock và Button để gọi hộp thoại. Trong trình xử lý sự kiện Click, chúng tôi khởi tạo cửa sổ InputDialogSample, cung cấp câu hỏi và câu trả lời mặc định, sau đó chúng tôi sử dụng phương thức ShowDialog() để hiển thị nó - bạn nên luôn luôn sử dụng phương thức ShowDialog() cho không phải phương thức hộp thoại như thế này.
Nếu kết quả của hộp thoại là đúng, có nghĩa là người dùng đã kích hoạt nút Ok bằng cách nhấp vào nó hoặc nhấn Enter, kết quả được gán cho tên Label. Đó là tất cả!