Como faço MenuHeaders personalizados no WPF com aceleradores?
Pergunta
Gostaria de criar alguns MenuHeaders personalizados no WPF para poder ter (por exemplo), um ícone e um texto em um item de menu.
Normalmente usando MenuItems, se você preencher o campo Cabeçalho com texto simples, poderá adicionar um acelerador usando um sublinhado.por exemplo, _Arquivo
Porém, se eu quisesse colocar um UserControl, acredito que essa função iria quebrar, como faria algo parecido com o seguinte?
<Menu>
<MenuItem>
<MenuItem.Header>
<UserControl>
<Image Source="..." />
<Label Text="_Open" />
</UserControl>
</MenuItem.Header>
</MenuItem>
...
Solução
Acho que a propriedade Icon atende às suas necessidades.
Porém, para responder à pergunta original, é possível manter a funcionalidade do Acelerador ao redigir o conteúdo do seu item de menu. Se você aninhou conteúdo em um MenuItem, você precisa definir explicitamente a propriedade AccessText como no primeiro abaixo.Quando você usa o formulário embutido, isso é resolvido automaticamente.
<Menu>
<MenuItem>
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="Images/Open.ico" />
<AccessText>_Open..</AccessText>
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem Header="_Close" />
</Menu>
Outras dicas
O problema é que você colocou a imagem dentro do conteúdo do MenuHeader, o que significa que você perderá a tecla aceleradora.Se você está apenas tentando colocar uma imagem no cabeçalho do menu, faça o seguinte.
<MenuItem Header="_Open">
<MenuItem.Icon>
<Image Source="images/Open.png"/>
</MenuItem.Icon>
</MenuItem>
Se você quiser personalizar ainda mais a aparência, modifique o modelo de controle e estilo para o menu.Por experiência própria, estilizar os menus e itens de menu é muito mais difícil do que estilizar os outros controles WPF.
Pensando primeiro, você pensaria que a propriedade Icon só pode conter uma imagem.Mas na verdade pode conter qualquer coisa!Descobri isso por acidente quando tentei programaticamente definir a propriedade Image diretamente para uma string com o caminho para uma imagem.O resultado foi que não mostrou a imagem, mas sim o próprio texto do caminho!Então descobri que primeiro precisava criar um elemento Image e defini-lo como a propriedade Icon.Isso me levou a pensar que a propriedade Image era apenas qualquer contêiner de conteúdo localizado na área de ícones à esquerda do menu, e eu estava certo.Tentei colocar um botão lá e funcionou!
Isso mostra um botão com o texto "i" na área Ícone do item de menu.Ao clicar no botão, o evento Button_Click é acionado (o LanguageMenu_Click NÃO é acionado quando você clica no botão).
<MenuItem Name="LanguageMenu" Header="_Language" Click="LanguageMenu_Click">
<MenuItem.Icon>
<Button Click="Button_Click">i</Button>
</MenuItem.Icon>
</MenuItem>
Isso leva a uma alternativa de não ter que fazer uma imagem para o ícone, mas usar texto com uma fonte de símbolo para exibir um simples "ícone".O exemplo a seguir usa a fonte Wingdings que contém um símbolo de disquete.Este símbolo na fonte é mapeado para o caractere <
, que tem um significado especial em XAML, então temos que usar a versão codificada <
em vez de.Isso funciona como um sonho!O seguinte mostra um símbolo de disquete como um ícone no item de menu:
<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
<MenuItem.Icon>
<Label VerticalAlignment="Center" HorizontalAlignment="Center"
FontFamily="Wingdings"><</Label>
</MenuItem.Icon>
</MenuItem>
@a7an:Ah, não percebi a propriedade Icon antes.Esse é um bom começo.
No entanto, especificamente, eu queria adicionar um 'botão' extra a alguns MenuItems para que pudesse ter um recurso 'Fixar' (consulte a lista de Documentos recentemente carregada no Office 2007 para obter a ideia do recurso).
Como também é necessário haver código, provavelmente precisarei subclassificar o controle e adicionar o código do botão?(Não tenho medo de mexer no template MenuItem, já tive que fazer isso uma vez e faria de novo se fosse necessário!;) )