My ribbon's application menu has several MenuTools in it. I was previously manually populating all those MenuItems with ButtonTools using procedural code, and was seeing proper results. The menus and buttons all looked good, like in Example 1 in my attached image.
I needed to switch to a binding approach to simplify all the internal wiring, so I converted to pure XAML for adding and populating these MenuTools in my application menu. I used an ImageSource to bind the MenuTool items to collections in my ViewModel, and used a DataTemplate specifying a ButtonTool for the MenuTool items.
Unfortunately the results aren't the same in the bound approach. The entire button content lives only in the very center of the MenuTool item. It's not using the LargeImage, and you have to click on that central button content to actually press the button. Ick.
Here's some XAML that manually adds a ButtonTool to a MenuTool, which gives the nice results like you see in Example 1 in my attached image:
<igRibbon:MenuTool Id="MyAccountMenu" Caption="My Account" LargeImage="/images/MyAccount_32.png"> <igRibbon:ButtonTool Id="ChangeXperiencePasswordButton" Caption="Change Xperience Password" SmallImage="/images/Key_16.png" LargeImage="/images/Key_32.png" Click="ChangeXperiencePasswordButton_Click" /></igRibbon:MenuTool>
Here's some XAML that shows the binding approach. This gives the icky results like you see in Example 2 in my attached image:
<igRibbon:MenuTool Id="SelectThemeMenu" Caption="Select Theme" LargeImage="/images/ThemePalette_32.png" UseLargeImages="True" ItemsSource="{Binding Themes}"> <igRibbon:MenuTool.ItemTemplate> <DataTemplate> <igRibbon:ButtonTool Caption="{Binding Path=Name}" SmallImage="/images/ThemePalette_16.png" LargeImage="/images/ThemePalette_32.png" Tag="{Binding}" Click="SelectThemeButton_Click" /> </DataTemplate> </igRibbon:MenuTool.ItemTemplate></igRibbon:MenuTool>
I'm not sure why manually adding a ButtonTool as the child of a MenuTool works, while specifying a ButtonTool as the DataTemplate for a MenuTool doesn't.
I feel like I must be missing something simple here. Please tell me I don't have to fall back on procedural code to make this work! :)
Thanks for your help,Jim Honeycutt
Hi Andrew,
I find a solution for this. It's almost embarrassing!
<
Setter Property="Icon" Value="{Binding LargeImage, Converter={StaticResource StringToUriConverter}}" />
Sometimes it helps to talk about it.
Robert
Hi Andrew
I have the same problem, but I have to set the Icon property dynamically. The ItemsSource is a list of CommandViewModels (see http://msdn.microsoft.com/en-us/magazine/dd419663.aspx). Especially for the ribbon i wrote a RibbonCommandViewModel class:
public class RibbonCommandViewModel : CommandViewModel { #region ctor
public RibbonCommandViewModel(string displayName, ICommand command, string largeImage, string smallImage) : this(displayName, command) { this.SmallImage = smallImage; this.LargeImage = largeImage; }
#endregion
#region Properties
string largeImage; public string LargeImage { get { return largeImage; } set { if (string.Equals(largeImage, value)) return; largeImage = value; OnPropertyChanged("LargeImage"); } }
string smallImage; public string SmallImage { get { return smallImage; } set { if (string.Equals(smallImage, value)) return; smallImage = value; OnPropertyChanged("SmallImage"); } }
#endregion }
Now I setting a databinding on the UriSource property.
<BitmapImage UriSource="{Binding LargeImage}"/>
When run, the application fails with an error, "Property 'UriSource' or property 'StreamSource' must be set.
Can you help me?
ahhh... sorry I missed the DataTemplate at the top.
Image is a UIElement. You can't set the value of a setter to an element instance since the style can be used for multiple instances and each would need its own element instance (i.e. something normally provided by a template/frameworkelementfactory). In the sample code I provided I set the Icon to an ImageSource (specifically a BitmapImage) and used a DataTemplate to create an Image element that would display the imagesource so I suspect you would have to do the same thing. Expose a property of type ImageSource and bind the Icon property to that and have a datatemplate for ImageSource.
Hi Andrew!
Is there a way to bind the Icon too? I tried something like:
<igRibbon:MenuTool.ItemContainerStyle> <Style TargetType="{x:Type igRibbon:ToolMenuItem}"> <Setter Property="igRibbon:ToolMenuItem.Icon"> <Setter.Value> <Image Source="{Binding ImageKey, Converter={StaticResource ImageResourceConverter}, Mode=OneWay}" /> </Setter.Value> </Setter> </Style></igRibbon:MenuTool.ItemContainerStyle>
(ImageResourceConverter is responsible for Icon-to-BitmapSource conversion)
When using the above Style, I get the following exception:
Cannot add content of type 'System.Windows.Controls.Image' to an object of type 'System.Object'.