views:

1880

answers:

4

I'd like to make some custom MenuHeaders in WPF so I can have (for example), an icon and text in a menu item.

Normally using MenuItems, if you populate the Header field with straight text, you can add an accelerator by using an underscore. eg, _File

However, if I wanted to put in a UserControl, I believe this function would break, how would I do something similar to the following?

<Menu>
<MenuItem>
    <MenuItem.Header>
    <UserControl>
        <Image Source="..." />
        <Label Text="_Open" />
    </UserControl>
    </MenuItem.Header>
</MenuItem>
...
+2  A: 

The problem is you placed the image inside of the content of the MenuHeader which means that you'll lose the accelerator key. If you're just trying to have an image in the menu header, do the following.

<MenuItem Header="_Open">
  <MenuItem.Icon>
    <Image Source="images/Open.png"/>
  </MenuItem.Icon>
</MenuItem>

If you want to customize the look and feel even further, modify the controltemplate and style for the menu. From experience, styling the menus and menuitems are much more difficult then styling the other WPF controls.

Alan Le
A: 

@a7an: Ah, I didn't notice the Icon property before. That's a good start.

However, specifically I wanted to add an extra 'button' to some MenuItems so I could have a 'Pin' feature (see the recently loaded Documents list in Office 2007 for the feature idea).

Since there needs to be code as well, will I probably need to subclass the control and add the code for the button? (Not affraid of messing with the MenuItem template, have already had to do it once and I'd do it again if I had to! ;) )

Nidonocu
+3  A: 

I think the Icon property fits your needs.
However to answer the original question, it is possible to retain the Accelerator functionality when you compose the content of your menuitem. If you have nested content in a MenuItem you need to define the AccessText property explicitly like in the first one below. When you use the inline form, this is automagically taken care of.

 <Menu> 
   <MenuItem>
      <MenuItem.Header>
        <StackPanel Orientation="Horizontal">
          <Image Source="Images/Open.ico" />      
          <AccessText>_Open..</AccessText>
        </StackPanel>
      </MenuItem.Header>
    </MenuItem>
    <MenuItem Header="_Close" />
   </Menu>
Gishu
This appears to be just what I need, I can insert a ToggleButton inside the stack to add the Pin functionality without needing to create any custom controls or breaking keyboard use. Thanks :)
Nidonocu
+1  A: 

First thought, you would think that the Icon property can only contain an image. But it can actually contain anything! I discovered this by accident when I programmatically tried to set the Image property directly to a string with the path to an image. The result was that it did not show the image, but the actual text of the path! Then I discovered that I had to create an Image element first and set that to the Icon property. This lead me to think that the Image property was just any content container that is located in the icon area at the left in the menu, and I was right. I tried to but a button there, and it worked!

This is showing a button with the text "i" in the Icon area of the menu item. When you click on the button, the Button_Click event is triggered (the LanguageMenu_Click is NOT triggered when you click the button).

<MenuItem Name="LanguageMenu" Header="_Language" Click="LanguageMenu_Click">
  <MenuItem.Icon>
    <Button Click="Button_Click">i</Button>
  </MenuItem.Icon>
</MenuItem>

This leads to an alternative to not have to make an image for the icon, but use text with a symbol font instead to display a simple "icon". The following example uses the Wingdings font which contains a "floppy" symbol. This symbol is the eqivalent to the charachter "<", which has special meaning in XAML, so we have to use the encoded version "<" instead. This works like a dream! The following shows a floppydisk symbol as an icon on the menu item:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>                
</MenuItem>
awe