【问题标题】:Using vector graphics from Inkscape in WPF in a resource effective matter在 WPF 中使用来自 Inkscape 的矢量图形进行资源有效处理
【发布时间】:2018-02-28 09:05:44
【问题描述】:

此问题旨在成为有关如何使用通过 Inkscape 创建并保存为 XAML 的图像的最佳实践。

互联网上有很多文章,但没有多少文章展示了每种解决方案的优缺点。 Example 1, Example 2

当您使用 Inkscape 创建图像并另存为 XAML 时,您在 XAML 中只会有一个 Viewbox。

<?xml version="1.0" encoding="UTF-8"?>
<!--This file is NOT compatible with Silverlight-->
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
  <Canvas Name="svg8" Width="210" Height="297">
    <Canvas.RenderTransform>
      <TranslateTransform X="0" Y="0"/>
    </Canvas.RenderTransform>
    <Canvas.Resources/>
    <!--Unknown tag: sodipodi:namedview-->
    <!--Unknown tag: metadata-->
    <Canvas Name="layer1">
      <Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="55.184521" Canvas.Top="113.30357" Width="33.261906" Height="33.261906" Name="rect4485" Fill="#FFFFFFFF" StrokeThickness="5.29166651" Stroke="#FF000000" StrokeMiterLimit="4"/>
    </Canvas>
  </Canvas>
</Viewbox>

要使用此文件,我通常必须将其包装在 ResourceDictionary 中。这很烦人,因为我无法再在 Inkscape 中编辑文件,而无需删除 ResourceDictionary

图像将多次显示,例如在ListViewItem 或任何其他具有ItemsSource 的元素中。

有没有办法让我只有一个 ResourceDictionary 可以导入所有这些 XAML 文件?

假设我已将其包装在 ResourceDictionary 中,并为 Viewbox 赋予了 x:Key="SquareIcon" 值。

展示这个元素最节省资源的方式是什么?

我是否应该使用ContentPresenter 并设置其Content 属性并设置Canvas x:Shared="false"

使用Label(或其他控件)是否更有效?

也许删除Viewbox 并在我自己的视图中始终在Viewbox 中使用Canvas

我应该将Viewbox 包装在ControlTemplate 中并在ContentPresenter Template 属性中使用它吗?这样我就不需要在Canvas 上使用x:Shared 属性。

【问题讨论】:

  • 我发现使用通过 Inkscape 生成的矢量图形时,它会为图形对象中使用的画笔使用相同的名称。因此,即使您为每个图形对象创建单独的字典,在解析 MergedDictionaries 时,名称也会在 xaml 中发生冲突。这只是仅供参考。您可能会创建一个包含所有图形对象的大型文件,然后将其作为 1 个文件导入。那么至少命名不会成为问题。

标签: c# wpf xaml


【解决方案1】:

将 Inkscape 中的资产保存为 xaml 时,您可以将其复制到 Blend,然后将其转换为 Path。然后,您就有了该资产的矢量表示,您可以轻松地将其合并为style

您可以阅读关于转换为路径here

请记住,您还可以组合多个元素然后转换它们。基本上,任何一种颜色的图像都可以转换为单一路径。

就最佳实践而言,我喜欢将所有与路径/图像/图标相关的样式保存在一个 ResourceDictionary 中,然后在 App.xaml 文件中全局引用它。

【讨论】:

    【解决方案2】:

    我认为您可以通过阅读所有文件来手动创建它。接下来是步骤: 1)您的项目中有 xaml 或 svg 的资源

    2) 创建您的markup extension,它将通过带有图标的嵌入式资源文件的路径提供 Geometry 的值。 (它应该解析并提供值)

    3) 创建一个自定义控件IconControl,用于显示具有依赖属性IconPath(字符串)的图标,并通过template binding将其绑定到您的模板中

      <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="controls:IconControl">
                    <Viewbox ><!--Could be other container -->
                         <Path Data="{TemplateBinding IconPath}"
                          Fill="{StaticResource DefaultBrush}" />
                    </Viewbox>
                </ControlTemplate>
    

    Viewbox 不太好,因为它对内容应用了转换。所以你应该使用最简单的容器来获得良好的性能。

    4) 在标记中使用您的控件

    <IconControl IconPath={locl:IconSvgMarkupExtension PathToYourEmbededResourceHere}/>
    

    我是在没有VS的情况下写的,凭记忆,所以可能会有一些错误。

    我是否应该将 Viewbox 包装在 ControlTemplate 中并在 ContentPresenter 模板属性?这样我就不需要使用 x:Canvas 上的共享属性。

    这也是一种可能的情况,几年前我使用了相同的方法,所以我的每个图标都是 ContentControl,根据图标的不同,它的模板也不同。

    【讨论】:

      【解决方案3】:

      我遇到了类似的问题:保存为 XAML 的 Inkscape svg 对我不起作用。

      经过长时间的搜索,我在 Youtube 上找到了这个非常快速但有用的视频:

      https://www.youtube.com/watch?v=otEV-skBqyI

      在此处与 Github 上可用的转换器结合使用:https://github.com/BerndK/SvgToXaml

      用于将 svg 转换为 DrawingImage 资源 (感谢 BerndK)

      它解决了我的问题!

      然后必须在我的项目中将资源文件另存为 .xaml

      Xaml 文件的内容

      <ResourceDictionary
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
          
          <DrawingImage x:Key="MyVectorImageName">
              <DrawingImage.Drawing>
                  <DrawingGroup ClipGeometry="M0,0 V297 H210 V0 H0 Z">
      .... //this part is the DrawingImage content Iget in converter and I copied pasted 
      </ResourceDictionary>
      

      并使用它:

      <Grid x:Name="gridImage" Margin="0,62.8,0,0" >
                                      <!-- Add vector ressource and display it  -->
      
                                      <Grid.Resources>
                                          <ResourceDictionary>
                                              <ResourceDictionary.MergedDictionaries>
                                                  <ResourceDictionary Source="images/MyVectorImageName.xaml"/>
                                              </ResourceDictionary.MergedDictionaries>
                                          </ResourceDictionary>
                                      </Grid.Resources> 
                                      <Image x:Name="imgName" Source="{StaticResource MyVectorImageName}"/>
                                  </Grid>
      

      注意:我将它添加为本地资源而不是全局资源(但我也可以)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-18
        • 1970-01-01
        • 2017-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多