2016-01-23 87 views
2

我的应用程序中有一个菜单直接从外部绑定的字符串列表中获取其内容(ItemsSource = Settings.RecentlyLoadedFiles)。这些字符串是文件名,当用户点击菜单中的某个项目时,该文件将被加载。禁用MenuItems的下划线解释

<ui:SplitButton 
    Grid.Column="0" 
    Command="{Binding LoadLogCommand}" ToolTip="Load log" ToolTipService.ShowOnDisabled="True" 
    Focusable="False" 
    ItemsSource="{Binding Settings.RecentlyLoadedFiles}" 
    MenuItem.Click="SplitButton_Click"> 
    <ui:SplitButton.Icon> 
     <ui:MenuIconImage Source="/Images/folder_open.png"/> 
    </ui:SplitButton.Icon> 
</ui:SplitButton> 

现在文件名可以很容易地在他们的下划线和WPF,因为认为它可能是一个快捷键,这是不显示。不是。但我怎么能告诉菜单?

有没有简单的方法来加倍这些下划线来显示其中之一。这份名单来自一个与此类事情无关的来源。

我是否需要编写一个自定义转换器将该列表转换为具有加倍下划线的字符串列表才能禁用该功能?

或者我需要从某处为菜单项复制整个模板,以在其中间的某个位置设置不同的特定属性?

是不是有一些附加属性或任何传播到解释将被完成的地方?

+0

Duplicate http://stackoverflow.com/questions/19769398/how-do-i-disable-mnemonics-in-a-wpf-menuitem/32998315#32998315 –

+0

有点解释:'MenuItem'包含一个'ContentPresenter '在它的'ControlTemplate'中,'RecognizesAccessKey'设置为'true'。我的观察是,它所做的是检测内容是什么,如果它是一个包含_的字符串,则它将内容包装在一个AccessText元素中,并将AccessKey设置为下划线后面的字符。我不知道有任何可能影响此功能的附加属性。在ContentPresenter之后将'RecognizesAccessKey'改为false也没有效果。下面给出的答案是一个可能的解决方案。 –

+0

@LonelyPixel - 你必须重写默认的MenuItem模板,并将'RecongnizesAccessKey'设置为'False',它应该可以工作。也许你可以在菜单资源中放置MenuItem的默认样式,这样你就不必为所有菜单项显式覆盖。 –

回答

0

如果您不能(或不想)加倍下划线并使用新的列表,您也可以不直接将字符串添加到菜单中,而是将每个字符串放在TextBlock中,并添加TextBlocks到菜单。

这段代码展示了两种技术都能按预期工作,没有第二和第三个加速器。

var s = "_UnderScore"; 
var mi = new MenuItem(); 
mi.Header = s; 
myMenu.Items.Add(mi); 

var d = "__UnderScore"; 
mi = new MenuItem(); 
mi.Header = d; 
myMenu.Items.Add(mi); 

var t = new TextBlock(); 
t.Text = s; 
mi = new MenuItem(); 
mi.Header = t; 
myMenu.Items.Add(mi); 

就个人而言,我通常会避免直接添加任何字符串的东西,如菜单,因为不约而同,你想要做的下一件事就是扩展解决方案添加图标的文件类型,显示悬停等工具提示这会将您带入使用控件或其他东西来“托管”每个菜单项的路径。

1

使用转换器。如果你不使用绑定,那么你可以在通过CommandParameter传递值,这里是你会怎么做在XAML:

<Menu DockPanel.Dock="Top"> 
     <Menu.Resources> 
      <converters:MenuTextConverter x:Key="MenuTextConverter" /> 
     </Menu.Resources> 
     <MenuItem Header="{Binding Converter={StaticResource MenuTextConverter}, ConverterParameter='_File'}" /> 
     <MenuItem Header="{Binding Converter={StaticResource MenuTextConverter}, ConverterParameter='_Edit'}" /> 
    </Menu> 

而且这里是你会怎么做它在代码隐藏:

 InitializeComponent(); // do this first 

     var menuItem1 = new MenuItem(); 
     var binding1 = new Binding(); 
     binding1.Converter = converter; 
     binding1.ConverterParameter = "_File"; 
     BindingOperations.SetBinding(menuItem1, MenuItem.HeaderProperty, binding1); 
     this.theMenu.Items.Add(menuItem1); 

     var menuItem2 = new MenuItem(); 
     var binding2 = new Binding(); 
     binding2.Converter = converter; 
     binding2.ConverterParameter = "_Edit"; 
     BindingOperations.SetBinding(menuItem2, MenuItem.HeaderProperty, binding2); 
     this.theMenu.Items.Add(menuItem2); 

下面是转换器本身代码:

public class MenuTextConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return parameter.ToString().Replace("_", "__"); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

如果您是通过再结合本身传递的菜单项字符串很明显,你只希望改变转换器使用value而不是parameter

+1

转换器过于激进并且会替换所有下划线,因为它只会用两个下划线替换一个前导下划线。除此之外,这可能是一个可行的解决方案,取决于OP如何将文件名绑定到他的菜单,以及他们是否曾经设计菜单项而不使用字符串。好的替代答案。 –

+0

@KoryGill好点,谢谢!我已经相应地更新了代码。 –

+0

我需要更新转换器以使用列表而不是单个字符串。我会将这部分代码添加到我的问题中。 – ygoe