MenuItem, который может отображать как .png, так и векторные изображения из свойства URI ресурса

1

У меня есть следующий стиль 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"); }
}

Теперь у меня есть большая библиотека векторной графики, доступная для меня, я хотел бы добавить возможность указать либо URI для.png ИЛИ какой-либо векторный графический ресурс, указанный в ресурсном словаре, что-то вроде

<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 чтобы я мог использовать BOTH 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);
    }
}
  • 0
    Вы можете применить что-то подобное из старого поста и таким образом добавить все, что хотите, и даже передать свойства зависимостей, чтобы на лету изменять такие вещи, как заполнение пути для разных цветов и т. Д. Очень просто.
  • 0
    Спасибо за это, но я хочу иметь возможность отображать ОБА .png изображения и векторные изображения. Это работает только для векторных изображений или я что-то пропустил?
Показать ещё 2 комментария
Теги:
xaml
wpf
mvvm
icons

1 ответ

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>

Теперь вам просто нужно объявить buch 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>

И это!

Ваша viewmodel будет иметь свойство так:

public IconPresentation Icon { get; private set; }

ps, я использовал "привязку ключей StaticResource", который по умолчанию недоступен. Это можно найти здесь: возможно ли динамическое создание ResourceKey для StaticResource? (например, с использованием привязки)

  • 0
    Большое спасибо за ваше время, это очень ценится. Я постараюсь реализовать это сейчас ...
  • 0
    Это не похоже на работу. Вы реализовали нечто подобное?
Показать ещё 9 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню