开发者

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!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜