开发者

Databound menu with icons

I have a simple markup given below. DataContext is assigned at run-time.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" MinHeight="5" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" MinHeight="5" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" MinWidth="5" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" MinWidth="5" />
    </Grid.ColumnDefinitions>

    <Menu Name="GlobalMenu" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
        <Menu.ItemContainerStyle>
            <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}">
                <Setter Property="Header" Value="{Binding Text}" />
                <Setter Property="Icon">
                    <Setter.Value>
                        <Image Source="{Binding Image}" />
                    </Setter.Value>
                </Setter>
                <Setter Property="ItemsSource" Value="{Binding Children}" />
            </Style>
        </Menu.ItemContainerStyle>
    </Menu>
</Grid>

The problem is that menu item icons are drwn only for the first time. So menu items still exist, text is there, I'm able to change menu item text by changing bound DataContext object, so binding generally works, but icon is not 开发者_如何学运维drawn. Since icons are a little bigger, I notice that not only icon is not drawn, but menu item shrinks in size, like there is no icon at all.

Icon property on bound object looks like this

    public BitmapImage Image
    {
        get
        {
            byte[] image = _widget.CommandRelation.Command.Element.Image;

            if (image == null)
            {
                return null;
            }

            BitmapImage bitmapImage = new BitmapImage();

            using (MemoryStream stream = new MemoryStream(image))
            {
                bitmapImage.BeginInit();
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.StreamSource = stream;
                bitmapImage.EndInit();
            }

            return bitmapImage;
        }
    }


If you create objects in a Style only one instance is created for all objects which use the style, this won't do as UI-elements can not be used in more than one place.

You can put the Image declaration in some (compiled) resource dictionary which is accessible from where the Style is used (Style.Resources are not compiled, so that will unfortunately not work) and set x:Shared on it to false, that way when you reference it in the Setter.Value via StaticResource a new instance is created every time and every MenuItem gets its own icon.

e.g. try this:

<Menu Name="GlobalMenu" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
    <Menu.Resources>
        <Image x:Key="Icon" x:Shared="False" Source="{Binding Image}" />
    </Menu.Resources>
    <Menu.ItemContainerStyle>
        <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}">
            <Setter Property="Header" Value="{Binding Text}" />
            <Setter Property="Icon" Value="{StaticResource Icon}"/>
            <Setter Property="ItemsSource" Value="{Binding Children}" />
        </Style>
    </Menu.ItemContainerStyle>
</Menu>
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜