我最近一直在使用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的内置方式?
对这个问题的篇幅表示歉意。我认为记录我的尝试可能会帮助有类似问题的人。
感谢。
答案 0 :(得分:0)
史蒂夫,
虽然这可能无法回答您的整个问题或直接解决您的问题,但它可能会帮助您“存储和重用xaml”:您可以使用 XamlReader <动态加载XAML或将对象写入XAML / strong>和 XamlWriter 类。我无法估计你是否真的会获得性能优势,但也许值得一试。
来自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);
祝你好运
答案 1 :(得分:0)
当您将Canvas
包裹在UserControl
中时,您正在做的事情是创建FrameworkTemplate
。 FrameworkTemplate
是一个抽象类,在文档中,“允许实例化FrameworkElement
和/或FrameworkContentElement
对象的树”,这是你真正的目标。
FrameworkTemplate
有两个具体的子类:ControlTemplate
和DataTemplate
。在XAML中创建UserControl
设置其Content
,用于构造其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>
这会在Canvas
的{{1}}中为集合中的每个ItemsControl
创建一个Canvas
(您的符号),位于Symbol
和Symbol.Top
属性说应该定位它。
通过模板选择器和Symbol.Left
类的正确设计,您可以使用数据绑定来构建整个图表。
修改强>
除了Symbol
和FrameworkTemplate
之外,还有ControlTemplate
的其他子类。一个出现在这篇文章中。