【问题标题】:MenuItem that can Show Both .png and Vector Based Images from a Resource URI Property可以显示来自资源 URI 属性的 .png 和基于矢量的图像的 MenuItem
【发布时间】:2015-01-15 16:53:41
【问题描述】:

我在资源字典中有以下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 样式,以便我可以同时使用 .png 的 URI 和矢量图形的 URI?

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

感谢您的宝贵时间。


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

<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);
    }
}

【问题讨论】:

  • 您可以应用this from an old post 之类的东西,这样就可以随意放入您想要的任何东西,甚至可以传递依赖属性来动态更改不同颜色的路径填充等内容。轻松愉快。
  • 感谢您,但我希望能够同时显示 .png 图像和基于矢量的图像。这仅适用于基于矢量的图像还是我错过了什么?
  • 它适用于您想要放入的任何内容。如果您按照该示例进行操作,则显示“在此处粘贴您的 xaml”的部分可以是您想要的任何内容。它可以是一个图像、一个路径、一堆控件、另一个视图,等等。然后,如果您希望它更具动态性,您可以对 Data= 或 Src= 之类的 TemplateBinding 或 Tag 之类的属性执行任何操作,并传入任何资源、字符串或任何您想要的内容。
  • 但正是缺少的 XAML 才是问题的症结所在。我可以要么拥有&lt;Image ...&gt;,在这种情况下,我将使用指向.png的URI,使用&lt;Rectangle ...&gt;&lt;Rectangle.Fill&gt;作为&lt;VisualBrush ...&gt;但我可以两者兼得。再说一次,我可能会遗漏一些东西,但如果你能提供一个简短的例子,那将不胜感激,我很乐意奖励一些代表!感谢你的宝贵时间。万事如意...

标签: c# wpf xaml mvvm icons


【解决方案1】:

首先,您需要更好地为您的类建模。矢量图形没有“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 键绑定”,默认情况下不可用。可以从这里找到:Is it possible to dynamically create a ResourceKey for a StaticResource? (eg using a Binding)

【讨论】:

  • 非常感谢您的宝贵时间,非常感谢。我现在将寻求实现这一点...
  • 这似乎不起作用。你实现过类似的东西吗?
  • 绑定到我的Icon 接口类型IIconPresentation(我由其他两个类继承)不起作用,它没有失败,它根本没有出现使用 Snoop 检查时的 ContentPresenter。有什么想法吗?
  • @Killercam:数据绑定引擎不适用于接口。你真的应该拥有我发布的那个(抽象类);)。
  • 天哪,我为什么要做这些事情。显然......再次感谢!
猜你喜欢
  • 2012-09-17
  • 2017-11-05
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多