2016-01-23 90 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