TOC

This article has been localized into Vietnamese by the community.

Điều khiển giao diện chung:

Điều khiển Menu WPF

Một trong những phần phổ biến nhất của ứng dụng Windows là menu, đôi khi được gọi là menu chính vì thường mỗi ứng dụng chỉ có duy nhất một menu. Menu này rất thiết thực vì nó cung cấp rất nhiều tùy chọn, chiếm rất ít không gian và mặc dù Microsoft đang thúc đẩy sử dụng Ribbon như một sự thay thế hữu hiệu cho menu và thanh công cụ cũ, nhưng chắc chắn Menu vẫn có một vị trí riêng của mình trong Toolbox.

WPF đi kèm với một control để tạo các menu gọi là ... Menu. Haha. Thêm các mục cho nó rất đơn giản - bạn chỉ cần thêm các phần tử MenuItem vào nó và ở mỗi phần tử      MenuItem có thể thêm một loạt các mục con, cho phép tạo các menu phân cấp như rất nhiều ứng dụng Windows mà chúng ta đã biết. Giờ, cùng nhảy thẳng đến một ví dụ mà chúng tôi sử dụng Menu:

<Window x:Class="WpfTutorialSamples.Common_interface_controls.MenuSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MenuSample" Height="200" Width="200">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_New" />
                <MenuItem Header="_Open" />
                <MenuItem Header="_Save" />
                <Separator />
                <MenuItem Header="_Exit" />
            </MenuItem>
        </Menu>
        <TextBox AcceptsReturn="True" />
    </DockPanel>
</Window>

Như trong hầu hết các ứng dụng Windows, menu của tôi được đặt ở sát trên cùng cửa sổ, nhưng để phù hợp với tính linh hoạt của WPF, bạn thực sự có thể đặt control menu bất cứ nơi nào bạn thích, ở bất kỳ chiều rộng hoặc chiều cao nào bạn muốn.

Tôi đã thiết lập một mục cấp cao nhất, với 4 mục con và dấu phân cách. Tôi sử dụng thuộc tính Header để định nghĩa tên của mục và bạn nên chú ý dấu gạch dưới trước ký tự đầu tiên của mỗi tên. Nó báo cho WPF sử dụng ký tự đó làm phím shortcut, có nghĩa là người dùng có thể nhấn phím Alt + ký tự đã cho để kích hoạt mục menu. Nó hoạt động ở tất cả các mục từ cấp cao nhất xuống phân cấp, nghĩa là trong ví dụ này tôi có thể nhấn Alt , sau đó F và sau đó N để kích hoạt mục New

Icons và checkboxes

Hai tính năng phổ biến của một mục menu là biểu tượng, thường dùng để dễ xác định mục menu, xem nó là gì, và để dễ nhận biết được mục menu, có thể bật và tắt một tính năng cụ thể. MenuItem của WPF hỗ trợ cả hai và rất dễ sử dụng:

<Window x:Class="WpfTutorialSamples.Common_interface_controls.MenuIconCheckableSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MenuIconCheckableSample" Height="150" Width="300">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Header="_Exit" />
            </MenuItem>
            <MenuItem Header="_Tools">
                <MenuItem Header="_Manage users">
                    <MenuItem.Icon>
                        <Image Source="/WpfTutorialSamples;component/Images/user.png" />
                    </MenuItem.Icon>
                </MenuItem>
                <MenuItem Header="_Show groups" IsCheckable="True" IsChecked="True" />
            </MenuItem>
        </Menu>
        <TextBox AcceptsReturn="True" />
    </DockPanel>
</Window>

Trong ví dụ này, ta đã tạo ra hai top-level menu item, ở đó ta thêm vào hai item: Cái đầu tiền là định nghĩa một icon bằng cách sử dụng thuộc tính Icon với một standard Image control bên trong, và cái còn lại sử dụng thuộc tính IsChecked giúp cho phép người dùng có thể chọn hoặc bỏ chọn item này. Trong code, cùng là một thuộc tính IsChecked bạn có thể biết item đó có đang được check hay không.

Sự kiện Clicks

Khi người dùng click vào menu item, thường bạn sẽ muốn nó thực hiện chuyện gì đó. Cách đơn giản nhất là thêm một sự kiện cho MenuItem, như thế này:

<MenuItem Header="_New" Click="mnuNew_Click" />

Ở phần code bạn sẽ phải cần làm vài thứ trong phương thức mnuNew_Click, như sau:

private void mnuNew_Click(object sender, RoutedEventArgs e)
{
	MessageBox.Show("New");
}

Làm thế này đi cho ứng dụng đơn giản hơn hoặc khi tạo ra nguyên mẫu cho một thứ gì đó, nhưng cách WPF làm là sử dụng Command cho việc này.

Keyboard shortcuts và Commands

Bạn có thể dễ dàng xử lý sự kiện Click của một mục menu như chúng tôi đã làm ở trên, nhưng cách tiếp cận phổ biến hơn là sử dụng các lệnh của WPF (WPF command). Có rất nhiều thứ cần biết về việc sử dụng và tạo command, nên chúng có nhiều danh mục bài viết riêng trên trang web này, nhưng giờ, tôi có thể nói với bạn rằng có một vài lợi thế khi sử dụng command trong WPF, đặc biệt là kết hợp với Menu hoặc Thanh công cụ.

Trước hết, họ đảm bảo rằng bạn có thể có cùng một hành động trên thanh công cụ, menu và thậm chí là menu ngữ cảnh, mà không phải thực hiện cùng một code ở nhiều nơi. Chúng cũng làm cho việc xử lý các phím tắt dễ dàng hơn rất nhiều, vì không giống như WinForms, WPF không tự động nghe các phím tắt nếu bạn gán chúng cho ví dụ: một mục menu - bạn sẽ phải làm điều đó bằng tay.

Tuy nhiên, khi sử dụng command, WPF tự động lắng nghe và sẽ tự động phản hồi phím tắt từ bàn phím. Tên (Header) của menu item là tên đặt tự động (mặc dù bạn có thể viết lại nó nếu cần), và InputGestureText cũng hiển thị cho người dùng biết phím tắt nào có thể sử dụng để gọi mục menu cụ thể. Giờ, cùng nhảy thẳng vào một ví dụ về việc kết hợp Menu với các lệnh WPF:

<Window x:Class="WpfTutorialSamples.Common_interface_controls.MenuWithCommandsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MenuWithCommandsSample" Height="200" Width="300">
    <Window.CommandBindings>
        <CommandBinding Command="New" CanExecute="NewCommand_CanExecute" Executed="NewCommand_Executed" />
    </Window.CommandBindings>
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_File">
                <MenuItem Command="New" />
                <Separator />
                <MenuItem Header="_Exit" />
            </MenuItem>
            <MenuItem Header="_Edit">
                <MenuItem Command="Cut" />
                <MenuItem Command="Copy" />
                <MenuItem Command="Paste" />
            </MenuItem>
        </Menu>

        <TextBox AcceptsReturn="True" Name="txtEditor" />
    </DockPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Input;

namespace WpfTutorialSamples.Common_interface_controls
{
	public partial class MenuWithCommandsSample : Window
	{
		public MenuWithCommandsSample()
		{
			InitializeComponent();
		}

		private void NewCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = true;
		}

		private void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			txtEditor.Text = "";
		}
	}
}

Nó có thể không hoàn toàn rõ ràng, nhưng bằng cách sử dụng các lệnh command, chúng tôi đã có được rất nhiều thứ thoải mái: Phím tắt, văn bản và InputGestureText trên các mục và WPF tự động bật/tắt các mục tùy thuộc vào việc kích hoạt control và trạng thái của nó. Trong trường hợp này, Cut và Copy bị vô hiệu hóa vì không có văn bản nào được chọn, nhưng Paste được bật, vì Clipboard của tôi không trống!

Và bởi vì WPF biết cách xử lý các lệnh nhất định kết hợp với các điều khiển nhất định, nên trong trường hợp này, các lệnh Cut/Paste/Copy kết hợp với control textbox, chúng tôi thậm chí không phải xử lý các sự kiện thực thi Execute của chúng - chúng hoạt động ngay lập tức! Chúng ta sẽ phải tự viết xử lý cho các lệnh command mới, khi WPF không thể đoán được chúng ta muốn gì khi người dùng kích hoạt nó. Điều này được thực hiện với CommandBindings của Window, tất cả được giải thích chi tiết trong bài viết về các lệnh command.

Tổng kết

Làm việc với điều khiển Menu WPF vừa nhanh vừa dễ, giúp đơn giản hóa việc tạo các phân cấp menu phức tạp và khi kết hợp nó với các lệnh WPF, bạn sẽ có được rất nhiều chức năng thoải mái.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!