首页 > 解决方案 > WPF SVG 图标资源

问题描述

有没有办法将 SVG 图标创建为可以在多个位置(例如 a Button、 aLabel和a 中的Icona )轻松工作的资源FileMenuItem

例子

应用程序.xaml

... 
<Application.Resources>
    <Icon x:Key="MyIcon" Data="...PathData..." />
</Application.Resources>
...

主窗口.xaml

...
<MenuItem Header="Do Stuff" Icon="{StaticResource MyIcon}" />
...
<StackPanel>
    <Label Content="{StaticResource MyIcon}" />
    <Button Content="{StaticResource MyIcon}" />
</StackPanel>
...

我试过的

我尝试将图标定义为Geometry和 aPath但两者都有并发症。在Geometry你必须指定一个Path元素并设置它的Data属性的情况下,这会给代码添加一堆杂乱无章的东西。在某些情况下使用 aPath可以解决这个问题,但对于FileMenuItem我发现我必须将路径包装在 aCanvas或 a中Border,再次为代码添加一些杂乱无章的东西。

标签: c#wpfxaml

解决方案


在做了一些研究和实验之后,我最终创建了一个UserControl将 a 包装在 aPath中的 aContentControl然后提供一对DependencyPropertys 以便可以设置图标DataStretch属性。

编码

SvgIcon.xaml.cs

public partial class SvgIcon : UserControl
{
    public SvgIcon()
    {
        InitializeComponent();
    }

    public Geometry Data
    {
        get { return (Geometry) GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public Stretch Stretch
    {
        get { return (Stretch) GetValue(StretchProperty); }
        set { SetValue(StretchProperty, value); }
    }

    public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(Geometry), typeof(SvgIcon));
    public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(SvgIcon));
}

SVG图标.cs

<UserControl x:Name="Root" ...etc...>
    <ContentControl>
        <Path Data="{Binding Data, ElementName=Root}" Fill="{Binding Foreground, ElementName=Root}" Stretch="{Binding Stretch, ElementName=Root}" />
    </ContentControl>
</UserControl>

示例用法

应用程序.xaml

... 
<Application.Resources>
    <myns:SvgIcon x:Key="MyIcon" Data="...PathData..." Foreground="Black" />
</Application.Resources>
...

主窗口.xaml

...
<MenuItem Header="Do Stuff" Icon="{StaticResource MyIcon}" />
...
<StackPanel>
    <Label Content="{StaticResource MyIcon}" />
    <Button Content="{StaticResource MyIcon}" />
</StackPanel>
...

使用这种方法有几个好处UserControl,主要是可以轻松地将样式应用于图标。然而,一个小痛点是将样式应用于资源文件之外的图标,例如更改文件菜单中的颜色。以下是如何实现这一目标的示例。

应用程序.xaml

... 
<Application.Resources>
    <myns:SvgIcon x:Key="MyIcon" Data="...PathData..." />
    ...
    /*Default Icon Style*/
    <Style TargetType="myns:SvgIcon">
        <Setter Property="Foreground" Value="Black" />
    </Style>

    /*Style icons used as content*/
    <Style TargetType="Control" x:Key="BlueIcon">
        <Style.Resources>
            <Style TargetType="myns:SvgIcon" BasedOn="{StaticResource {x:Type myns:SvgIcon}}">
                <Setter Property="Foreground" Value="Blue" />
            </Style>
        </Style.Resources>
    </Style>
    ...
</Application.Resources>
...

主窗口.xaml

...
<MenuItem Header="Do Stuff" Icon="{StaticResource MyIcon}" Style="{StaticResource BlueIcon}" />
...
<StackPanel>
    <Label Content="{StaticResource MyIcon}" Style="{StaticResource BlueIcon}" />
    <Button Content="{StaticResource MyIcon}" Style="{StaticResource BlueIcon}" />
</StackPanel>
...

可能还有其他聪明的解决方案,但这对于我想要实现的目标非常有效。


推荐阅读