使用XAML文件作为矢量图像源

22

我希望能够使用矢量图形,最好是用XAML定义的,作为图像控件的源,就像我目前可以使用像PNG这样的光栅图像一样。这样我就可以轻松地混合和匹配位图和矢量图像,就像这样:

<StackPanel>
    <Image Source="Images/Namespace.png"/>
    <Image Source="Images/Module.xaml"/>
</StackPanel>

Module.xaml的根元素最可能是<DrawingImage>而不是<UserControl>

实际上,我真正想要的是这样的,这样我的ViewModel就可以根据需要选择光栅或矢量图像:

<Image Source="{Binding ImageUri}"/>

这是否可行?Image.Source能否从给定的URI加载XAML类?还是只能加载位图资源?


7
让我想想...为什么在WPF/Silverlight中使用XAML图像会这么困难,或者不被原生支持...考虑到WPF/Silverlight是基于XAML的! - Jacques
3个回答

21

你可以直接将矢量图形作为静态资源引用:

<Image Source="{StaticResource MyImage}" />

将图像存储在ResourceDictionary中,以DrawImage的形式。 Expression Blend可以帮助您生成这些内容:

<ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

   <DrawingImage x:Key="MyImage">
      <DrawingImage.Drawing>
         <DrawingGroup>
            <DrawingGroup.Children>
               <GeometryDrawing Brush="Black" Geometry="M 333.393,... 100.327 Z "/>
               <GeometryDrawing Brush="Black" Geometry="F1 M 202.309,... Z "/>
                      :
            </DrawingGroup.Children>
         </DrawingGroup>
     </DrawingImage.Drawing>
   </DrawingImage>

</ResourceDictionary>

1
当然。但这并不能直接帮助我解决数据绑定的情况。 - Joe White
当与此博客文章中讨论的“方法3”相结合时,可以实现简单而优雅的方式。 - Siva Gopal

2

1) 将DrawingImage.xaml添加到项目中,并将其属性设置为“BuildAction = Content”和“Copy Always”。或者,您也可以从外部动态加载XAML,因为我将要解释的逻辑也适用于loose-xaml。

2) 编写转换器将XAML uri转换为UIELement,在您的情况下,它将始终是DrawingImage。

public class FileToUIElementConverter :IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        FileStream fileStream = new FileStream((string)parameter, FileMode.Open); 
        return XamlReader.Load(fileStream) as DrawingImage;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

3) 将XAML编写为以下内容:

<Window.Resources>
    <local:FileToUIElementConverter x:Key="uriToUIElementConverter"/>
</Window.Resources>
<Grid>
    <Image Stretch="Fill" Source="{Binding Converter={StaticResource uriToUIElementConverter},ConverterParameter=ImageDrawing.xaml}"/>
</Grid>

我不认为FileStream可以从已编译的资源(pack:// URI)中加载,它能吗? - Joe White
这里有一个处理资源的转换器:http://stackoverflow.com/a/21588195/418362 - Artfunkel

1

将类型为“Resource”的XAML资源(DrawingImage)嵌入其中。然后它不是一个单独的文件,可以通过URI直接引用,就像您原来的示例一样--但是URI并不简单。您必须弄清楚Microsoft的“pack” URI语法并使用它。


它没有被记录,但是“pack” URI内部不会加载到内存中,直到您实例化第一个UIElement之后。因此,在App.cs中尝试使用它(甚至在您的MainWindow.xaml加载之前)会非常令人沮丧。相反,请在MainWindow_Load处理程序中使用它。 - Jesse Chisholm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接