【发布时间】:2011-04-01 09:07:54
【问题描述】:
有人可以描述一个推荐的分步过程吗?
步骤 1。将 SVG 转换为 XAML……很简单
步骤 2。现在呢?
【问题讨论】:
-
很抱歉复活这篇文章,但我认为这些信息很有价值:SVG 本质上是与 WPF 路径的一对一匹配。因此,除了一些表面的标记调整之外,您应该能够将 SVG 直接带入您的 WPF 应用程序。最多您可能必须将路径托管到画布中,但仅此而已,恕我直言。
有人可以描述一个推荐的分步过程吗?
步骤 1。将 SVG 转换为 XAML……很简单
步骤 2。现在呢?
【问题讨论】:
您的技术将取决于您的 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>
如果您需要控制大小,也可以将其包含在 Viewbox 中:
<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}" />
在 Viewbox 中绑定 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>
【讨论】:
<ResourceDictionary><DataTemplate x:Key="MyIconTemplate"><Canvas ... /></DataTemplate></ResourceDictionary> ... <Button><ContentPresenter ContentTemplate="{StaticResource MyIconTemplate}" /></Button>。
<ResourceDictionary><VisualBrush x:Key="MyBrush"><VisualBrush.Visual><Canvas x:Key="MyCanvas" ... /></VisualBrush.Visual></VisualBrush></ResourceDictionary> ... <Button><Rectangle Fill="{StaticResource MyBrush}" Width="..." Height="..." /></Button>。这更难,因为您还必须确保 Canvas 得到测量/排列,并且您必须对宽度/高度进行硬编码(或使用矩形模板)。
Canvas 对象,我将 SVG 放在哪里?这很重要,因为我的 SVG 都在静态资源中,我需要嵌入它们...
Install-Package SharpVectors
<UserControl xmlns:svgc="http://sharpvectors.codeplex.com/svgc">
<svgc:SvgViewbox Source="/Icons/icon.svg"/>
</UserControl>
【讨论】:
Windows 10 build 15063“Creators Update”本机支持面向 Windows 10 的 UWP/UAP 应用程序的 SVG 图像(尽管存在一些问题)。
如果您的应用程序是 WPF 应用程序而不是 UWP/UAP,您仍然可以使用此 API(在经历了相当多的麻烦之后):Windows 10 build 17763 “October 2018 Update”引入了XAML 岛(作为“预览”技术,但我相信在应用商店中允许使用;在所有情况下,Windows 10 build 18362“2019 年 5 月更新”XAML 岛不再是预览功能并且完全受支持)允许您使用 UWP WPF 应用程序中的 API 和控件。
您需要首先add the references to the WinRT APIs,并使用某些与用户数据或系统交互的 Windows 10 API(例如,在 Windows 10 UWP webview 中从磁盘加载图像或使用 toast 通知 API 来显示 toast ),您还需要将您的 WPF 应用程序与包标识 as shown here 相关联(在 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>
但是,SVG 图像以这种方式加载(通过 XAML)may load jagged/aliased。一种解决方法是指定一个 RasterizePixelHeight 或 RasterizePixelWidth 值,它是你的实际高度/宽度的两倍:
<SvgImageSource RasterizePixelHeight="300" RasterizePixelWidth="300" UriSource="Assets/svg/icon.svg" /> <!-- presuming actual height or width is under 150 -->
这可以通过在基本图像的ImageOpened 事件中创建一个新的SvgImageSource 来动态解决:
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 使用初始SvgImageSource,第二个Image 使用在ImageOpened 事件中创建的SvgImageSource:
这是上图的放大图:
而这是底部(抗锯齿,正确)图像的放大视图:
(您需要在新标签页中打开图像并以全尺寸查看以了解差异)
【讨论】:
您可以将 SVG 生成的 xaml 用作矩形上的绘图笔刷。像这样的:
<Rectangle>
<Rectangle.Fill>
--- insert the converted xaml's geometry here ---
</Rectangle.Fill>
</Rectangle>
【讨论】:
使用 SvgImage 或 SvgImageConverter 扩展,SvgImageConverter 支持绑定。 有关演示这两种扩展的示例,请参阅以下链接。
https://github.com/ElinamLLC/SharpVectors/tree/master/TutorialSamples/ControlSamplesWpf
【讨论】:
经过各种搜索和尝试,我设法找到了该方法,而无需使用外部库。 首先您需要使用Inkscape打开SVG文件进行准备,然后按照以下列表进行操作:
<path>,您可以查看多个路径。这是一个例子:<path d="..." fill="..." id="path2"/>
<path d="..." fill="..." id="path4"/>
<path d="..." fill="..." id="path6"/>
ViewBox 元素,然后插入一个 Grid 元素和 Path 元素,以便在 SVG 文件中看到路径的次数:<Viewbox Stretch="Fill">
<Grid>
<Path Fill="..." Data="..."/>
<Path Fill="..." Data="..."/>
<Path Fill="..." Data="..."/>
</Grid>
</Viewbox>
在 XAML 的 Fill 属性中,您必须在 SVG 文件中插入 fill 属性,在 XAML 的 Data 属性中,您必须在 SVG 文件中插入 d 属性。
【讨论】:
我们可以直接使用SVG代码中的路径代码:
<Path>
<Path.Data>
<PathGeometry Figures="M52.8,105l-1.9,4.1c ...
【讨论】:
另一种选择是 dotnetprojects SVGImage
这允许直接在 xaml 中本地使用 .svg 文件。
好的部分是,它只有一个组件,大约 100k。与任何许多文件都大得多的sharpvectors相比。
用法:
...
xmlns:svg1="clr-namespace:SVGImage.SVG;assembly=DotNetProjects.SVGImage"
...
<svg1:SVGImage Name="mySVGImage" Source="/MyDemoApp;component/Resources/MyImage.svg"/>
...
就是这样。
见:
【讨论】:
Build Action 属性设置为 Resource
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
xmlns:local="clr-namespace:WpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<Button Height="100">
<svgc:SvgViewbox Source="/Icons/Checkmark_16x.svg"/>
</Button>
<ContentControl Height="100">
<svgc:SvgViewbox Source="/Icons/CollapseAll_16x.svg"/>
</ContentControl>
<Label Height="100">
<svgc:SvgViewbox Source="/Icons/Refresh_16x.svg"/>
</Label>
</StackPanel>
</Grid>
</Window>
SvgToXaml.exe BuildDict /inputdir "c:\Icons" /outputdir "c:\MyWpfApp" /outputname IconsDictionary
IconsDictionary.xaml 文件添加到您的项目中并在您的代码中使用:<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="IconsDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<StackPanel>
<Button Height="100">
<Image Source="{StaticResource Refresh_16xDrawingImage}"/>
</Button>
<ContentControl Height="100">
<Image Source="{StaticResource CollapseAll_16xDrawingImage}"/>
</ContentControl>
<Label Height="100">
<Image Source="{StaticResource Checkmark_16xDrawingImage}"/>
</Label>
</StackPanel>
</Grid>
</Window>
如果您已经生成了 XAML 文件并且想要使用它们,则可以为其中的某些类型创建自定义 ValueConverter 类。更多信息请参考以下答案:
【讨论】: