WPF在WPF中将SVG文件用作图标的正确方法是什么


78

有人可以描述推荐的逐步操作步骤吗?

编辑:

第1步。将SVG转换为XAML ...就这么简单

第2步。怎么办?


11
抱歉,请重新发布此帖子,但我认为此信息有价值:SVG本质上是与WPF路径一对一的匹配。因此,除了一些表面上的标记调整之外,您还应该能够将SVG正确地引入WPF应用程序中。至多,您可能必须将Path托管到Canvas中,但这就是IMHO。
code4life

Answers:


155

您的技术将取决于SVG到XAML转换器生成的XAML对象。它会产生图纸吗?一个图像?网格?画布?一条路径?几何?在每种情况下,您的技术都会有所不同。

在下面的示例中,我将假定您在按钮上使用图标,这是最常见的情况,但是请注意,对于任何ContentControl,相同的技术都适用。

使用工程图作为图标

若要使用绘图,请使用DrawingBrush绘制适当大小的矩形:

<Button>
  <Rectangle Width="100" Height="100">
    <Rectangle.Fill>
      <DrawingBrush>
        <DrawingBrush.Drawing>

          <Drawing ... /> <!-- Converted from SVG -->

        </DrawingBrush.Drawing>
      </DrawingBrush>
    </Rectangle.Fill>
  </Rectangle>
</Button>

使用图像作为图标

图像可以直接使用:

<Button>
  <Image ... />  <!-- Converted from SVG -->
</Button>

使用网格作为图标

网格可以直接使用:

<Button>
  <Grid ... />  <!-- Converted from SVG -->
</Button>

或者,如果需要控制大小,则可以将其包含在“视图”框中:

<Button>
  <Viewbox ...>
    <Grid ... />  <!-- Converted from SVG -->
  </Viewbox>
</Button>

使用画布作为图标

这就像使用图像或网格一样,但是由于画布没有固定的大小,因此您需要指定高度和宽度(除非SVG转换器已经设置了高度和宽度):

<Button>
  <Canvas Height="100" Width="100">  <!-- Converted from SVG, with additions -->
  </Canvas>
</Button>

使用路径作为图标

您可以使用路径,但是必须设置笔触或显式填充:

<Button>
  <Path Stroke="Red" Data="..." /> <!-- Converted from SVG, with additions -->
</Button>

要么

<Button>
  <Path Fill="Blue" Data="..." /> <!-- Converted from SVG, with additions -->
</Button>

使用几何作为图标

您可以使用路径绘制几何图形。如果应该对其进行笔划,请设置笔划:

<Button>
  <Path Stroke="Red" Width="100" Height="100">
    <Path.Data>
      <Geometry ... /> <!-- Converted from SVG -->
    </Path.Data>
  </Path>
</Button>

或者如果应该填充,请设置填充:

<Button>
  <Path Fill="Blue" Width="100" Height="100">
    <Path.Data>
      <Geometry ... /> <!-- Converted from SVG -->
    </Path.Data>
  </Path>
</Button>

如何进行数据绑定

如果要在代码中执行SVG-> XAML转换,并希望使用数据绑定显示结果XAML,请使用以下方法之一:

绑定工程图:

<Button>
  <Rectangle Width="100" Height="100">
    <Rectangle.Fill>
      <DrawingBrush Drawing="{Binding Drawing, Source={StaticResource ...}}" />
    </Rectangle.Fill>
  </Rectangle>
</Button>

绑定图像:

<Button Content="{Binding Image}" />

绑定网格:

<Button Content="{Binding Grid}" />

在视图框中绑定网格:

<Button>
  <Viewbox ...>
    <ContentPresenter Content="{Binding Grid}" />
  </Viewbox>
</Button>

绑定画布:

<Button>
  <ContentPresenter Height="100" Width="100" Content="{Binding Canvas}" />
</Button>

绑定路径:

<Button Content="{Binding Path}" />  <!-- Fill or stroke must be set in code unless set by the SVG converter -->

绑定几何:

<Button>
  <Path Width="100" Height="100" Data="{Binding Geometry}" />
</Button>

10
+10只是花时间在所有情况下作为示例在我的情况下,我有一块画布,所以我假设以下内容适用<Button> <Canvas Height =“ 100” Width =“ 100”> <!-从SVG转换而来,还有- -> </ Canvas> </ Button>但是我该如何重用呢?我无法为要使用svg图像的每个按钮执行复制/粘贴操作。我想将其定义为字典中的资源,并用作Static / DynamicResource。
NVM

4
您不能在UI的多个位置使用单个Canvas,因为Visual只能有一个父对象。因此,您通常会为此使用模板。模板允许你创建画布的一个单独的实例每个需要它的地方:<ResourceDictionary><DataTemplate x:Key="MyIconTemplate"><Canvas ... /></DataTemplate></ResourceDictionary>... <Button><ContentPresenter ContentTemplate="{StaticResource MyIconTemplate}" /></Button>
雷·伯恩斯

1
一种更有效但更复杂的方法是使用VisualBrush创建Canvas的图片,以便使用:<ResourceDictionary><VisualBrush x:Key="MyBrush"><VisualBrush.Visual><Canvas x:Key="MyCanvas" ... /></VisualBrush.Visual></VisualBrush></ResourceDictionary>...绘制 <Button><Rectangle Fill="{StaticResource MyBrush}" Width="..." Height="..." /></Button>。这比较难,因为您还必须确保已测量/布置了画布,并且必须对宽度/高度进行硬编码(或为矩形使用模板)。
Ray Burns 2010年

啊哈!我知道我不能直接使用同一张画布两次,这就是为什么答案尚未被接受的原因。非常感谢。
NVM 2010年

1
因此,基本上,对于每个元素-例如Canvas对象,我应将SVG放在哪里?这很重要,因为我的SVG都在静态资源中,因此我需要将它们嵌入...
code4life 2016年

52

安装SharpVectors

Install-Package SharpVectors

在XAML中添加以下内容

<UserControl xmlns:svgc="http://sharpvectors.codeplex.com/svgc">
    <svgc:SvgViewbox Source="/Icons/icon.svg"/>
</UserControl>

6
将XAML Imges嵌入到应用程序中还是使用这种方法更好?
MyOwnWay 2015年

对我来说效果很好...与nugets和所有功能兼容。我必须正确地使用颜色信息制作svg,但是一旦解决,它们就不会显示为黑色,但是看起来不错。
kfn

1
这是使用Sharpvector绑定到Source AttachedProperty的方法:stackoverflow.com/a/35088090/828184
CodingYourLife

2020年更新有一个新版本使用SharpVectors.Reloaded
Andy Braham

1
2020年11月:无论内容如何,​​SvgViewbox的Source属性的1.7.0引发NullReference异常。降级到1.6.0(SharpVectors.Reloaded),它在那里工作。
Volodymyr Kotylo

7

Windows 10内部版本15063“创建者更新”本机支持针对Windows 10的UWP / UAP应用程序的SVG图像(尽管有些陷阱)。

如果您的应用程序是WPF应用程序,而不是UWP / UAP,则仍然可以使用此API(在经历了很多麻烦之后):Windows 10 build 17763“ October 2018 Update”引入了XAML孤岛的概念(作为“预览”技术,但我相信应用商店中允许;在所有情况下,Windows 10 build 18362“ May 2019 Update” XAML岛不再是预览功能,完全受支持),您可以在WPF中使用UWP API和控件应用程序。

您需要首先添加对WinRT API的引用,并使用与用户数据或系统进行交互的某些Windows 10 API(例如,从Windows 10 UWP Webview中的磁盘加载映像,或使用Toast通知API来显示Toast),您还需要将WPF应用程序与程序包身份相关联,如此处所示(在Visual Studio 2019中非常容易)。Windows.UI.Xaml.Media.Imaging.SvgImageSource但是,使用该类不是必需的。

用法(如果您使用的是UWP,或者已按照上述说明进行操作,并在WPF下添加了XAML岛支持),则Source只需<Image />将设置为到SVG的路径即可。这等效于使用SvgImageSource,如下所示:

<Image>
    <Image.Source>
        <SvgImageSource UriSource="Assets/svg/icon.svg" />
    </Image.Source>
</Image>

但是,以这种方式(通过XAML)加载的SVG图像可能会加载锯齿/锯齿。一种解决方法是指定一个RasterizePixelHeightRasterizePixelWidth值为实际高度/宽度的两倍以上的值:

<SvgImageSource RasterizePixelHeight="300" RasterizePixelWidth="300" UriSource="Assets/svg/icon.svg" /> <!-- presuming actual height or width is under 150 -->

可以通过在基本映像SvgImageSourceImageOpened事件中创建一个新值来动态地解决此问题:

var svgSource = new SvgImageSource(new Uri("ms-appx://" + Icon));
PrayerIcon.ImageOpened += (s, e) =>
{
    var newSource = new SvgImageSource(svgSource.UriSource);
    newSource.RasterizePixelHeight = PrayerIcon.DesiredSize.Height * 2;
    newSource.RasterizePixelWidth = PrayerIcon.DesiredSize.Width * 2;
    PrayerIcon2.Source = newSource;
};
PrayerIcon.Source = svgSource;

在非高dpi的屏幕上,混叠可能很难看到,但是这里尝试说明这一点。

这是上面代码的结果:一个Image使用initial SvgImageSourceImage下面一个使用在ImageOpened事件中创建的SvgImageSource :

在此处输入图片说明

这是顶部图像的放大视图:

在此处输入图片说明

而这是底部(抗锯齿,正确)图像的放大视图:

在此处输入图片说明

(您需要在新标签页中打开图像并以完整尺寸查看,以欣赏它们之间的区别)


14
遗憾的是,SvgImageSource是一个UWP库,而不是WPF。
adam_0

5
这是UWP,而不是WPF;您对XAML感到困惑
-juFo

3

您可以将SVG中生成的xaml用作矩形上的绘图笔刷。像这样:

<Rectangle>
   <Rectangle.Fill>
      --- insert the converted xaml's geometry here ---
   </Rectangle.Fill>
</Rectangle>

3
与第一个答案相同的问题。我不想每次都想使用相同的svg时复制粘贴。
NVM 2010年


1

另一种选择是dotnetprojects SVGImage

这允许直接在xaml中本地使用.svg文件。

好的部分是,它只有一个组件,大约需要100k。与sharpvectors相比,sharpvectors的文件要大得多。

用法:

...
xmlns:svg1="clr-namespace:SVGImage.SVG;assembly=DotNetProjects.SVGImage"
...
<svg1:SVGImage Name="mySVGImage" Source="/MyDemoApp;component/Resources/MyImage.svg"/>
...

就这样。

看到:


0

我们可以直接使用SVG代码中的路径代码:

    <Path>
        <Path.Data>
            <PathGeometry Figures="M52.8,105l-1.9,4.1c ... 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.