Using a DrawingImage as Icon for Multiple MenuItems - wpf

I have some icon resources as DrawingImages that is made up of many GeometryDrawings. I have File MenuItems and ToolBar buttons that use these images via resource bindings to MenuItem.Icon. Unfortunately, only one of the MenuItems show the icon.
I am sure you can't assign a single DrawingImage resource to many MenuItem.Icon (or anything else for that matter), but I don't know of an alternative. I would prefer not to duplicate the DrawingImage resource, but if I have too I guess I will.

You assign an Image control to the Icon Property and set the DrawingImage into the Image.Source property.
In XAML:
<MenuItem>
<MenuItem.Icon>
<Image Source="{StaticResource myDrawingImage}"/>
</MenuItem.Icon>
<!-- everyhting else -->
</MenuItem>
In C#:
menuItem.Icon = new Image() {Source = (ImageSource)Resources["myDrawingImage"]};

Related

Access icon resources through URI VB.NET

I have a WPF VB.NET application and I want to use an icon embedded in the applications resources as a menu icon. So far I have this code (in the window's initialized event):
MenuItem.Icon = New Image() With {.Source = New BitmapImage(New
Uri("Resources\Icon.ico", UriKind.Relative))}
And the icon is still not displayed, any ideas?
The problem is your URI. If you set it in code behind, you must write the full WPF Pack URI. You must also set the Build Action
of the icon file to Resource (the default value for icons is None).
MenuItem.Icon = New Image() With
{
.Source = New BitmapImage(New Uri("pack://application:,,,/Resources/Icon.ico"))
}
When you specify the URI in XAML, the default ImageSource TypeConverter will add the pack://application:,,, part, and you could simply write
<Image Source="/Resources/Icon.ico"/>
Better option is building menu in XAML:
Create folder Images in your solution
Add image as Resources to Images directory (in my sample code: "Icon.ico")
In XAML you can use following code:
...
<MenuItem Header="Item1">
<MenuItem.Icon>
<Image Source="/Images/Icon.ico" Width="20" Height="20" />
</MenuItem.Icon>
</MenuItem>
Or if you want to do this in code-behind you can use following code instead of step 3:
MenuItem.Icon = New Image() With {.Source = New BitmapImage(New Uri("/Images/Icon.ico", UriKind.RelativeOrAbsolute))}

Code-behind static/dynamic properties in WPF and Naming Conundrum

I have a button defined in my XAML which has a button style and a vector graphic, it is defined thus:
<Button
Height="48"
Width="48"
mvp:Presenter.Action="CreateStudentApplication"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="5"
Grid.Column="3"
Style="{DynamicResource BaseButton2}">
<ContentControl Template="{StaticResource ApplicationVector}"/>
</Button>
In my code-behind, I have a method that dynamically adds new buttons similar to this one to a StackPanel. In brief, it does something to the tune of:
var button = new Button();
button.Height = 48;
button.Width = 48;
button.Tag = x.ID;
button.SetResourceReference(TemplateProperty, "ApplicationVector");
button.SetResourceReference(StyleProperty, "BaseButton2");
Now here's the weird part- It displays only the vector graphic, and no button behind it. When I remove the penultimate line (the line with the vector reference), it displays the button styled as it should be! I'm assuming that setting the template is overriding the style, however they seem to play amicably in XAML. I have also tried setting the ContentProperty instidead of TemplateProperty, but this resulted in a string of the type. Any ideas? Thank you!
Your XAML and code behind are not equivalent. In the XAML, you are setting the Content property of the button to be a ContentControl. In the code behind, you are setting the Template (or Content) property to be the ApplicationVector resource.
You would need to set the Content property of the button to be an instance of a ContentControl whose Template property is set to be your ApplicationVector resource.
var contentControl = new ContentControl();
contentControl.SetResourceReference(TemplateProperty, "ApplicationVector");
button.Content = contentControl;

Make a silverlight textblock act like a hyperlink

I'm pretty new to silverlight. I have a text block that is displayed inside a datagrid
(inside a DataGridTemplateColumn.CellTemplate template to be precise).
I'd like to dynamically make some of the textblocks into hyperlinks that open a new window.
Is there a way to do this - so far all I can come up with is using a hyperlink button and trying to style it to look like a text block.
Any help would be very much appreciated.
HyperlinkButton is a ContentControl so it can actually take some kind of pre-styled TextBlock (or other control) as it's content (instead of just using a simple string as Content).
<HyperlinkButton NavigateUri="http://myurl.com">
<TextBlock Text="My Link Text" Foreground="Black" />
</HyperlinkButton>
You would have to use a custom HyperlinkButton template if you wanted to style it to get rid of the default teal colored focus ring, etc. You could also set the IsEnabled property of the HyperlinkButton to false to prevent link behavior on any cells that weren't actually links if you are trying to set them up in some dynamic way.

Silverlight button style

I am trying out new styles with silverlight, and I created a new button skin with blend that consists of a border and a textblock. Wondered if there is a way to change the the text of the textblock when the the button's content(text) property is changed.
The binding would look like this:
<TextBlock Text="{TemplateBinding Content}"/>
The problem is when I try to set the content to something other than text:
<Button>
<Button.Content>
<Rectangle Fill="#FFB51111"/>
</Button.Content>
</Button>
In this case using the ContentPresenter would work better. It uses the same binding expression, but can display more than text. But all that is really up to you.
I don't really get what your trying to do. Normally, you include a TextBlock like that as a part of the button content.
Use a ContentPresenter rather than a TextBlock in your Template.

How do I make custom MenuHeaders in WPF with accelerators?

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>
...
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>
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.
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 put 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 floppydisk symbol. This symbol in the font is mapped 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"><</Label>
</MenuItem.Icon>
</MenuItem>
#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! ;) )

Resources