可以显示来自资源 URI 的 .png 和基于矢量的图像的菜单项 属性

MenuItem that can Show Both .png and Vector Based Images from a Resource URI Property

我在资源字典中有以下 MenuItem 样式

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:Controls="clr-namespace:GambitFramework.Modules.MainMenu.Controls"
                    xmlns:Converters="clr-namespace:GambitFramework.Core.Converters"
                    xmlns:Behaviors="clr-namespace:GambitFramework.Modules.MainMenu.Behaviors">
    <Converters:NullableValueConverter x:Key="NullableValueConverter"/>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    <Image x:Key="MenuItemIcon" 
             x:Shared="false" 
             Source="{Binding IconSource, Converter={StaticResource NullableValueConverter}}"/>
    <Style x:Key="MenuItem" TargetType="{x:Type Controls:MenuItemEx}">
        <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
        <Setter Property="InputGestureText" Value="{Binding InputGestureText}"/>
        <Setter Property="Icon" Value="{StaticResource MenuItemIcon}"/>
        <Setter Property="IsCheckable" Value="{Binding IsChecked, Mode=OneWay}"/>
        <Setter Property="IsChecked" Value="{Binding IsChecked, Mode=OneWay}"/>
        <Setter Property="Command" Value="{Binding Command}"/>
        <Setter Property="Behaviors:MenuBehavior.UpdateCommandUiItems" Value="True"/>
    </Style>
    <HierarchicalDataTemplate x:Key="MenuTemplate" ItemsSource="{Binding Children}">
        <ContentPresenter Content="{Binding Path=Text}" RecognizesAccessKey="True"/>
    </HierarchicalDataTemplate>
</ResourceDictionary>

这适用于 .png 资源类型,我的 IconSource 属性 可能类似于

public override Uri IconSource
{
    get { return new Uri("pack://application:,,,/GambitFramework;component/Resources/Icons/Undo.png"); }
}

现在,我有一个可供我使用的大型矢量图形图标库,我想添加指定 .png 的 URI 或资源字典中指定的某些矢量图形资源的功能,例如

<ResourceDictionary x:Class="resources_icons_xaml"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <Canvas x:Key="appbar_acorn" Width="48" Height="48" Clip="F1 M 0,0L 48,0L 48,48L 0,48L 0,0">
        <Path Width="22.3248" Height="25.8518" Canvas.Left="13.6757" Canvas.Top="11.4012" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 16.6309,18.6563C 17.1309,8.15625 29.8809,14.1563 29.8809,14.1563C 30.8809,11.1563 34.1308,11.4063 34.1308,11.4063C 33.5,12 34.6309,13.1563 34.6309,13.1563C 32.1309,13.1562 31.1309,14.9062 31.1309,14.9062C 41.1309,23.9062 32.6309,27.9063 32.6309,27.9062C 24.6309,24.9063 21.1309,22.1562 16.6309,18.6563 Z M 16.6309,19.9063C 21.6309,24.1563 25.1309,26.1562 31.6309,28.6562C 31.6309,28.6562 26.3809,39.1562 18.3809,36.1563C 18.3809,36.1563 18,38 16.3809,36.9063C 15,36 16.3809,34.9063 16.3809,34.9063C 16.3809,34.9063 10.1309,30.9062 16.6309,19.9063 Z "/>
    </Canvas>
    ...
</ResourceDictionary>

如何修改我的 MenuItem 样式,以便我可以将 URI 用于 .png 和 URI 用于矢量图形?

我主要感兴趣的是如何在 XAML 中以适当的方式区分和显示资源,我从未见过这样做,我对如何去做感到困惑。

感谢您的宝贵时间。


在以前的系统版本中,我只有矢量图形支持,XAML MenuItem 样式是

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:Caliburn="http://www.caliburnproject.org"
                    xmlns:Converters="clr-namespace:GambitFramework.Core.Converters"
                    xmlns:Controls="clr-namespace:GambitFramework.Modules.MainMenu.Controls">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary>
            <Converters:StringToResourceConverter x:Key="StringToResourceDictionary"/>
        </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>
    <Rectangle x:Key="MenuItemIcon" x:Shared="False" 
               Visibility="{Binding IconVisibility}"
               HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
               Width="16" Height="16">
        <Rectangle.Fill>
            <VisualBrush Stretch="Uniform" Visual="{Binding IconSource}"/>
        </Rectangle.Fill>
    </Rectangle>
    <Style x:Key="MenuItem" TargetType="{x:Type Controls:MenuItemEx}">
        <Setter Property="Icon" Value="{StaticResource MenuItemIcon}"/> 
        <Setter Property="InputGestureText" Value="{Binding InputGestureText}"/>
        <Setter Property="Caliburn:Action.Target" Value="{Binding}"/>
        <Setter Property="Caliburn:Message.Attach" Value="{Binding ActionText}"/>
    </Style>
    <Style x:Key="CheckableMenuItem" 
           TargetType="{x:Type Controls:MenuItemEx}"
           BasedOn="{StaticResource MenuItem}">
        <Setter Property="IsCheckable" Value="True"/>
        <Setter Property="IsChecked" Value="{Binding IsChecked}"/>
    </Style>
    <HierarchicalDataTemplate x:Key="MenuTemplate" 
                              ItemsSource="{Binding Children}">
        <ContentPresenter Content="{Binding Path=Text}" RecognizesAccessKey="True"/>
    </HierarchicalDataTemplate>
</ResourceDictionary>

绑定源所在的位置

public Canvas IconSource
{
    get { return iconSource; }
    set
    {
        iconSource = value;
        IconVisibility = iconSource == null ?
            Visibility.Collapsed :
            Visibility.Visible;
        NotifyOfPropertyChange(() => IconSource);
    }
}

首先,您需要更好地建模 类。矢量图形没有"URI"。

从这里开始:

public abstract class IconPresentation{}
public sealed class ImageIconPresentation : IconPresentation
{
    private readonly string _url;

    public Uri IconSource
    {
        get { return new Uri(_url); }
    }

    public ImageIconPresentation(string url){
        _url = url;
    }
}

public sealed class ResourceIconPresentation : IconPresentation
{
    public string Name
    {
        get;
        private set;
    }

    public ResourceIconPresentation(string name){
        Name = name;
    }
}

完成后,您必须修改 Icon 的模板:

<Setter Property="Icon"> 
 <Setter.Value>
   <ContentControl Content="{Binding Icon}"/>
 </Setter.Value>
</Setter>

现在您只需要为每个图标显示声明 DataTemplate 组。

<DataTemplate DataType="{x:Type ImageIconPresentation}">
  <Image Source="{Binding IconSource}" />
</DataTemplate>

<DataTemplate DataType="{x:Type ResourceIconPresentation}">
    <Rectangle ..>
        <Rectangle.Fill>
            <VisualBrush Stretch="Uniform" 
               Visual="{ext:ResourceKeyBinding Path=Name}"/>
        </Rectangle.Fill>
    </Rectangle>
</DataTemplate>

就是这样!

您的视图模型会 属性 这样:

public IconPresentation Icon { get; private set; }

ps,我用的是"StaticResource key binding",默认没有。可以从这里找到:Is it possible to dynamically create a ResourceKey for a StaticResource? (eg using a Binding)