How do you bind menu items to a ContextMenu in silverlight, including the icon
I have a context menu and i want its menu items populated via a binding. The following code works
<Button>
<controlsInputToolkit:ContextMenuService.ContextMenu>
<controlsInputToolkit:ContextMenu ItemsSource="{Binding MenuItems}">
<controlsInputToolkit:ContextMenu.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</controlsInputToolkit:ContextMenu.ItemTemplate>
</controlsInputToolkit:ContextMenu>
</controlsInputToolkit:ContextMenuService.ContextMenu>
</Button>
but there's one problem, the ItemTemplate represents the Text area of a menu item and so as far as im aware doesnt allow you to set the icon
so i tried doing the binding via the ItemContainerStyle as in the below example
<Button>
<controlsInputToolk开发者_Go百科it:ContextMenuService.ContextMenu>
<controlsInputToolkit:ContextMenu ItemsSource="{Binding MenuItems}">
<controlsInputToolkit:ContextMenu.ItemContainerStyle>
<Style TargetType="controlsInputToolkit:MenuItem">
<Setter Property="Header" Value="{Binding Name}"/>
</Style>
</controlsInputToolkit:ContextMenu.ItemContainerStyle>
</controlsInputToolkit:ContextMenu>
</controlsInputToolkit:ContextMenuService.ContextMenu>
</Button>
but silverlight doesnt seem to like that
any ideas?
I create a context menu programmatically and setting the content to the MenuItem.Header property seems to work just fine for images. There are a lot of examples of setting text.
Try using this open source menu instead:
http://sl4popupmenu.codeplex.com
The template allows binding of images directly. Hope this helps.
I've had the same question, and though I did not find the answer I wanted, I found a workaround that met my needs nicely. I thought you might like to see it, even this long after-the-fact.
It appears that if the ItemsSource
of the ContextMenu
class contains MenuItem
objects, then the icon lands nicely where it belongs. I, like you, was using a view model and didn't what to inject UI logic into my view model class.
What I did instead was implement a value converter to transform my view model into MenuItem
objects. It looked a little something like this:
XAML:
<UserControl.Resources>
<local:DelegatedValueConverter
x:Key="LocalContextItemConverter"
Converting="OnBindingContextMenu" />
</UserControl.Resources>
...
<toolkit:ContextMenu
ItemsSource="{Binding ContextMenuItems, Converter={StaticResource LocalContextItemConverter}}" />
C# Code-Behind
private void OnBindingContextMenu(object sender, ValueConvertingEventArgs e)
{
var dataitems = e.Value as IEnumerable< NavigationItemViewModel >;
if (dataitems != null)
{
var items = dataitems.Select(data => new MenuItem()
{
Header = data.Title,
Icon = data.Icon,
Tag = data
}).ToList();
var handler = new RoutedEventHandler(this.OnContextMenuClick);
items.ForEach(item => item.Click += handler);
e.Result = items
}
}
private void OnContextMenuClick(object sender, RoutedEventArgs e)
{
}
Discussion
The DelegatedValueConverter
is a little something I describe in detail here, but it is not really important. You could roll your own value converter and use it instead.
The Title
property of my view model is a string, and Icon
is an instance of Image
. I use the Tag
property of the menu item to keep a reference to my view model so that I can refer to the non-visual data in it during a click event.
This solution is convenient because it still provides some separation between the UI and the view model, though I would prefer in this case a purely-declarative solution.
I hope this helps!
精彩评论