英文:
How do you underline AccessKey characters (mnemonics) in applications built using WinAppSDK/WinUI?
问题
Microsoft的辅助功能指南对于Win32应用程序开发要求为菜单项分配访问键:
为所有菜单项分配访问键。没有例外。
在Win32应用程序中,可以通过在菜单项的分配文本字符串中放置一个和符号来实现这一点,该符号代表要加下划线的字符。例如,"&File"
将呈现字符串 File
,但字符 F
将被加下划线:
我正在尝试了解如何在使用WinUI的Windows App SDK应用程序中实现相同的功能。
我知道可以在 MenuBarItem
控件上设置 AccessKey
属性。这模仿了Microsoft Office在Ribbon控件中使用访问键的实现方式。它会导致指定的字符在按下 Alt
键后出现在工具提示中。
例如,这个标记:
<MenuBar>
<MenuBarItem Title="File" AccessKey="F" />
</MenuBar>
在用户按下 Alt
键后会呈现如下内容:
但是这个标记不会导致 F
字符被加下划线,以便用户在按下 Alt
键之前就知道访问键的存在(假设在设置中启用了“始终显示加下划线的访问键”选项,这在Win32应用程序中是默认的)。
根据此文档,您必须使用 <Underline/>
元素手动执行这项操作:
访问键的下划线文本装饰不会自动提供。如果希望在UI中显示带下划线的文本,您必须在您的助记符中显式为特定键的文本添加内联下划线格式。
但是 AccessKey
属性的类型是 string
,因此我不清楚如何将其设置为包含 <Underline/>
元素的文本块。
因此,使用上面的示例标记,我的问题是如何使“File”菜单项中的 F
字符带有下划线。
英文:
Microsoft's accessibility guidance for Win32 application development is to assign access keys to menu items:
> Assign access keys to all menu items. No exceptions.
In Win32 applications, this is done by placing an ampersand in a menu item's assigned text string, which represents the character that is to be underlined. For example, "&File"
would render the string File
, but the F
character would be underlined:
I'm trying to understand how to accomplish this same thing in a Windows App SDK application that's using WinUI.
I'm aware of the AccessKey
property that can be set on a MenuBarItem
control. This mimics Microsoft Office's implementation of access keys in the Ribbon control. It causes the specified character to appear in a tooltip after the Alt
key is pressed.
For example, this markup:
<MenuBar>
<MenuBarItem Title="File" AccessKey="F" />
</MenuBar>
Will render this after the user presses the Alt
key:
But that markup doesn't result in the F
character being underlined so that the user knows about the access key's existence before having to press the Alt
key (as is the case for Win32 applications, assuming that "Always underline access keys" is enabled in Settings).
According to this document, you have to do this manually using the <Underline/>
element:
> The underline text decoration for an access key is not provided automatically. You must explicitly underline the text for the specific key in your mnemonic as inline Underline formatting if you wish to show underlined text in the UI.
But the AccessKey
property is of type string
, so it's unclear to me how to set this to a text block that includes an <Underline/>
element.
So using the example markup above, my question is how to make the F
character underlined in the "File" menu item.
答案1
得分: 1
关于这个问题有一个讨论,但目前来说,据我所知,没有内置的方法来实现这个。
您可以创建一个自定义的 MenuBarItem
,覆盖 Title
属性,将其从 string
类型更改为 object
类型:
MenuBarItemEx.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace MenuBarExample
{
public sealed class MenuBarItemEx : MenuBarItem
{
public static new readonly DependencyProperty TitleProperty =
DependencyProperty.Register(
nameof(Title),
typeof(object),
typeof(MenuBarItemEx),
new PropertyMetadata(default, OnTitlePropertyChanged));
public MenuBarItemEx()
{
this.DefaultStyleKey = typeof(MenuBarItem);
}
public new object Title
{
get => GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
private Button? ContentButton { get; set; }
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (GetTemplateChild("ContentButton") is Button contentButton)
{
ContentButton = contentButton;
ContentButton.Content = Title;
}
}
private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MenuBarItemEx menuBarItemEx &&
menuBarItemEx.ContentButton is Button contentButton)
{
contentButton.Content = e.NewValue;
}
}
}
}
现在您可以这样做:
<MenuBar>
<local:MenuBarItemEx AccessKey="F">
<local:MenuBarItemEx.Title>
<RichTextBlock>
<Paragraph CharacterSpacing="0">
<!-- 这必须在一行中,否则在 'F' 和 'ile' 之间会有一个空格 -->
<Underline>F</Underline><Run>ile</Run>
</Paragraph>
</RichTextBlock>
</local:MenuBarItemEx.Title>
</local:MenuBarItemEx>
</MenuBar>
英文:
There's a discussion about this but for the moment, AFAIK, there's no built-in way to do this.
What you can do is to create a custom MenuBarItem
that overrides the Title
property from string
to object
:
MenuBarItemEx.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace MenuBarExample;
public sealed class MenuBarItemEx : MenuBarItem
{
public static new readonly DependencyProperty TitleProperty =
DependencyProperty.Register(
nameof(Title),
typeof(object),
typeof(MenuBarItemEx),
new PropertyMetadata(default, OnTitlePropertyChanged));
public MenuBarItemEx()
{
this.DefaultStyleKey = typeof(MenuBarItem);
}
public new object Title
{
get => GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
private Button? ContentButton { get; set; }
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (GetTemplateChild("ContentButton") is Button contentButton)
{
ContentButton = contentButton;
ContentButton.Content = Title;
}
}
private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MenuBarItemEx menuBarItemEx &&
menuBarItemEx.ContentButton is Button contentButton)
{
contentButton.Content = e.NewValue;
}
}
}
Now you can do this:
<MenuBar>
<local:MenuBarItemEx AccessKey="F">
<local:MenuBarItemEx.Title>
<RichTextBlock>
<Paragraph CharacterSpacing="0">
<!-- This have to be in a single line
unless you'll get a space between 'F' and 'ile' -->
<Underline>F</Underline><Run>ile</Run>
</Paragraph>
</RichTextBlock>
</local:MenuBarItemEx.Title>
</local:MenuBarItemEx>
</MenuBar>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论