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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3526366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:02:30  来源:igfitidea点击:

WPF What is the correct way of using SVG files as icons in WPF

wpfsvg

提问by NVM

Can someone describe a recommended Step by Step procedure for doing this?

有人可以描述推荐的逐步执行此操作的程序吗?

EDIT:

编辑:

Step1. Convert SVG to XAML... thats easy

第1步。将 SVG 转换为 XAML……这很简单

Step2. Now what?

第2步。怎么办?

回答by Ray Burns

Your technique will depend on what XAML object your SVG to XAML converter produces. Does it produce a Drawing? An Image? A Grid? A Canvas? A Path? A Geometry? In each case your technique will be different.

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

In the examples below I will assume you are using your icon on a button, which is the most common scenario, but note that the same techniques will work for any ContentControl.

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

Using a Drawing as an icon

使用绘图作为图标

To use a Drawing, paint an approriately-sized rectangle with a DrawingBrush:

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

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

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

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

Using an Image as an icon

使用图像作为图标

An image can be used directly:

可以直接使用图像:

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

Using a Grid as an icon

使用网格作为图标

A grid can be used directly:

可以直接使用网格:

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

Or you can include it in a Viewbox if you need to control the size:

或者,如果您需要控制大小,可以将其包含在 Viewbox 中:

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

Using a Canvas as an icon

使用 Canvas 作为图标

This is like using an image or grid, but since a canvas has no fixed size you need to specify the height and width (unless these are already set by the SVG converter):

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

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

Using a Path as an icon

使用路径作为图标

You can use a Path, but you must set the stroke or fill explicitly:

您可以使用 Path,但您必须明确设置笔触或填充:

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

or

或者

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

Using a Geometry as an icon

使用几何图形作为图标

You can use a Path to draw your geometry. If it should be stroked, set the Stroke:

您可以使用路径来绘制几何图形。如果应该描边,设置描边:

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

or if it should be filled, set the Fill:

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

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

How to data bind

如何进行数据绑定

If you're doing the SVG -> XAML conversion in code and want the resulting XAML to appear using data binding, use one of the following:

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

Binding a Drawing:

绑定图纸:

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

Binding an Image:

绑定图像:

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

Binding a Grid:

绑定网格:

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

Binding a Grid in a Viewbox:

在 Viewbox 中绑定网格:

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

Binding a Canvas:

绑定画布:

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

Binding a Path:

绑定路径:

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

Binding a Geometry:

绑定几何:

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

回答by fastobject

I found best way to me to use svg icon in WPF. I use sharpvectorframework:

我找到了在 WPF 中使用 svg 图标的最佳方法。我使用sharpvector框架:

Install-Package SharpVectors

So my XAML looks like following:

所以我的 XAML 如下所示:

<UserControl ...
         xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
         ...>
    ...
    <svgc:SvgViewbox Margin="5" Height="20" Width="20" Stretch="Uniform" Source="/View/Resources/Icons/Connection.Closed.Black.svg"/>
    ...
</UserControl>

回答by Mahmoud Al-Qudsi

Windows 10 build 15063 "Creators Update" natively supports SVG images (though with some gotchas) to UWP/UAP applications targeting Windows 10.

Windows 10 build 15063“Creators Update”本机支持 SVG 图像(尽管有一些问题)到面向 Windows 10 的 UWP/UAP 应用程序。

If your application is a WPF app rather than a UWP/UAP, you can still use this API (after jumping through quite a number of hoops): Windows 10 build 17763 "October 2018 Update" introduced the concept of XAML islands (as a "preview" technology but I believe allowed in the app store; in all cases, with Windows 10 build 18362 "May 2019 Update" XAML islands are no longer a preview feature and are fully supported) allowing you to use UWP APIs and controls in your WPF applications.

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

You need to first add the references to the WinRT APIs, and to use certain Windows 10 APIs that interact with user data or the system (e.g. loading images from disk in a Windows 10 UWP webview or using the toast notification API to show toasts), you also need to associate your WPF application with a package identity, as shown here(immensely easier in Visual Studio 2019). This shouldn't be necessary to use the Windows.UI.Xaml.Media.Imaging.SvgImageSourceclass, though.

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

Usage (if you're on UWP or you've followed the directions above and added XAML island support under WPF) is as simple as setting the Sourcefor an <Image />to the path to the SVG. That is equivalent to using SvgImageSource, as follows:

用法(如果您使用的是 UWP,或者您已按照上述说明操作并在 WPF 下添加了 XAML 岛支持)就像将Sourcefor an设置为<Image />SVG 的路径一样简单。这相当于使用SvgImageSource,如下所示:

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

However, SVG images loaded in this way (via XAML) may load jagged/aliased. One workaround is to specify a RasterizePixelHeightor RasterizePixelWidthvalue that is double+ your actual height/width:

但是,以这种方式(通过 XAML)加载的 SVG 图像可能会加载 jagged/aliased。一种解决方法是指定一个RasterizePixelHeightorRasterizePixelWidth值,该值是两倍+您的实际高度/宽度:

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

This can be worked around dynamically by creating a new SvgImageSourcein the ImageOpenedevent for the base image:

这可以通过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;

The aliasing may be hard to see on non high-dpi screens, but here's an attempt to illustrate it.

在非高 dpi 屏幕上可能很难看到锯齿,但这里尝试说明它。

This is the result of the code above: an Imagethat uses the initial SvgImageSource, and a second Imagebelow it that uses the SvgImageSource created in the ImageOpenedevent:

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

enter image description here

在此处输入图片说明

This is a blown up view of the top image:

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

enter image description here

在此处输入图片说明

Whereas this is a blown-up view of the bottom (antialiased, correct) image:

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

enter image description here

在此处输入图片说明

(you'll need to open the images in a new tab and view at full size to appreciate the difference)

(您需要在新选项卡中打开图像并以全尺寸查看以了解差异)

回答by Gus Cavalcanti

You can use the resulting xaml from the SVG as a drawing brush on a rectangle. Something like this:

您可以将 SVG 生成的 xaml 用作矩形上的画笔。像这样的东西:

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

回答by Paulus

Use the SvgImage or the SvgImageConverter extensions, the SvgImageConverter supports binding. See the following link for samples demonstrating both extensions.

使用 SvgImage 或 SvgImageConverter 扩展,SvgImageConverter 支持绑定。有关演示这两种扩展的示例,请参阅以下链接。

https://github.com/ElinamLLC/SharpVectors/tree/master/TutorialSamples/ControlSamplesWpf

https://github.com/ElinamLLC/SharpVectors/tree/master/TutorialSamples/ControlSamplesWpf

回答by Soleil - Mathieu Prévot

We can use directly the path's code from the SVG's code:

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

    <Path>
        <Path.Data>
            <PathGeometry Figures="M52.8,105l-1.9,4.1c ...