Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF有效地重用Xaml_C#_Wpf_Xaml - Fatal编程技术网

C# WPF有效地重用Xaml

C# WPF有效地重用Xaml,c#,wpf,xaml,C#,Wpf,Xaml,我最近一直在做一个使用WPF生成图表的项目。在本文中,我必须在符号旁边显示文本,这些符号说明了与文本相关的信息 为了绘制符号,我最初使用了一些我制作的png图像。在我的图表中,这些图像看起来很模糊,放大后看起来更糟。为了改进这一点,我决定使用矢量而不是rastor图像格式。下面是我从文件路径获取rastor图像的方法: protected Image GetSymbolImage(string symbolPath, int symbolHeight) { Image symbol =

我最近一直在做一个使用WPF生成图表的项目。在本文中,我必须在符号旁边显示文本,这些符号说明了与文本相关的信息

为了绘制符号,我最初使用了一些我制作的png图像。在我的图表中,这些图像看起来很模糊,放大后看起来更糟。为了改进这一点,我决定使用矢量而不是rastor图像格式。下面是我从文件路径获取rastor图像的方法:

protected Image GetSymbolImage(string symbolPath, int symbolHeight)
{
    Image symbol = new Image();
    symbol.Height = symbolHeight;
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.BeginInit();
    bitmapImage.UriSource = new Uri(symbolPath);
    bitmapImage.DecodePixelHeight = symbolHeight;
    bitmapImage.EndInit();
    symbol.Source = bitmapImage;
    return symbol;
}
不幸的是,这无法识别矢量图像格式。因此,我使用了如下方法,其中“path”是指向.xaml格式矢量图像的文件路径:

public static Canvas LoadXamlCanvas(string path)
{
    //if a file exists at the specified path
    if (File.Exists(path))
    {
        //store the text in the file
        string text = File.ReadAllText(path);                

        //produce a canvas from the text
        StringReader stringReader = new StringReader(text);
        XmlReader xmlReader = XmlReader.Create(stringReader);
        Canvas c = (Canvas)XamlReader.Load(xmlReader);

        //return the canvas
        return c;
    }

    return null;
}
这虽然有效,但在反复调用时会大大降低性能

我发现文本到画布转换所需的逻辑(见上文)是性能问题的主要原因,因此嵌入.xaml图像并不能单独解决性能问题

我尝试只在应用程序的初始加载时使用此方法,并将生成的画布存储在字典中,以后可以更快地访问该字典,但后来我意识到,在使用字典中的画布时,我必须复制它们。我在网上找到的所有与制作副本相关的逻辑都使用了XamlWriter和XamlReader,这同样会带来性能问题

我使用的解决方案是将每个.xaml图像的内容复制到它自己的用户控件中,然后在适当的地方使用这些用户控件。这意味着我现在显示的矢量图形和性能要好得多

然而,这个解决方案对我来说似乎相当笨拙。我是WPF新手,想知道是否有一些内置的方法可以在整个应用程序中存储和重用xaml

为这个问题的长度道歉。我想记录下我的尝试可能会对有类似问题的人有所帮助

谢谢。

史蒂夫

虽然这可能无法回答您的全部问题或直接解决您的问题,但它可能有助于“存储和重用xaml”:您可以使用类动态加载xaml或将对象写入xaml。我无法估计您是否真的会获得性能优势,但也许值得一试

MSDN中的示例:

// Create the Button.
Button origianlButton = new Button();
origianlButton.Height = 50;
origianlButton.Width = 100;
origianlButton.Background = Brushes.AliceBlue;
origianlButton.Content = "Click Me";

// Save the Button to a string.
string savedButton = XamlWriter.Save(origianlButton);

// Load the button
StringReader stringReader = new StringReader(savedButton);
XmlReader xmlReader = XmlReader.Create(stringReader);
Button readerLoadButton = (Button)XamlReader.Load(xmlReader);
向史蒂夫问好

虽然这可能无法回答您的全部问题或直接解决您的问题,但它可能有助于“存储和重用xaml”:您可以使用类动态加载xaml或将对象写入xaml。我无法估计您是否真的会获得性能优势,但也许值得一试

MSDN中的示例:

// Create the Button.
Button origianlButton = new Button();
origianlButton.Height = 50;
origianlButton.Width = 100;
origianlButton.Background = Brushes.AliceBlue;
origianlButton.Content = "Click Me";

// Save the Button to a string.
string savedButton = XamlWriter.Save(origianlButton);

// Load the button
StringReader stringReader = new StringReader(savedButton);
XmlReader xmlReader = XmlReader.Create(stringReader);
Button readerLoadButton = (Button)XamlReader.Load(xmlReader);

最好的祝愿

当您将
画布
包装在
用户控件
中时,您的基本工作是创建一个
框架模板
FrameworkTemplate
是一个抽象类,文档中说,“能够实例化
FrameworkElement
和/或
FrameworkContentElement
对象的树”,这是您的真正目标

FrameworkTemplate
有两个具体的子类:
ControlTemplate
DataTemplate
。在XAML中创建
UserControl
将设置其
内容,该内容用于构造其
ControlTemplate
,以便每次实例化
UserControl
时,它都会实例化该模板中的所有对象

您可以改为创建一个
ControlTemplate
,然后在创建其他类型的控件时使用它。或者——这可能是最好的方法——您可以创建一个
DataTemplate

例如,考虑这个XAML:

<DataTemplate TargetType="Symbol">
   <Canvas Canvas.Top="{Binding Top}" Canvas.Left="{Binding Left}">
      <!-- XAML to construct the symbol goes here -->
   </Canvas>
</DataTemplate>

现在您可以执行以下操作:

<ItemsControl ItemsSource="{StaticResource SomeCollectionOfSymbolObjects}">
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
         <Canvas/>
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
</ItemsControl>

这将在
项控件的
画布中为集合中的每个
符号
创建
画布
(您的符号),放置在
符号的位置。顶部
符号。左侧
属性表示应该放置该符号

通过使用模板选择器和
Symbol
类的适当设计,您可以使用数据绑定来构建整个图表

编辑


除了
ControlTemplate
DataTemplate
之外,还有
FrameworkTemplate
的其他子类。一个出现在这篇文章中。

当你将
画布
包装在
用户控件
中时,你基本上在做的是创建一个
框架模板
FrameworkTemplate
是一个抽象类,文档中说,“能够实例化
FrameworkElement
和/或
FrameworkContentElement
对象的树”,这是您的真正目标

FrameworkTemplate
有两个具体的子类:
ControlTemplate
DataTemplate
。在XAML中创建
UserControl
将设置其
内容,该内容用于构造其
ControlTemplate
,以便每次实例化
UserControl
时,它都会实例化该模板中的所有对象

您可以改为创建一个
ControlTemplate
,然后在创建其他类型的控件时使用它。或者——这可能是最好的方法——您可以创建一个
DataTemplate

例如,考虑这个XAML:

<DataTemplate TargetType="Symbol">
   <Canvas Canvas.Top="{Binding Top}" Canvas.Left="{Binding Left}">
      <!-- XAML to construct the symbol goes here -->
   </Canvas>
</DataTemplate>

现在您可以执行以下操作:

<ItemsControl ItemsSource="{StaticResource SomeCollectionOfSymbolObjects}">
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
         <Canvas/>
      </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
</ItemsControl>

这将在
项控件的
画布中为集合中的每个
符号创建一个
画布
(您的符号),位于
符号.Top
符号.Left
属性指定的位置