[英]WPF, how can I optimize lines and circles drawing?
我正在开发一个需要在屏幕上绘制图形的应用程序。 为此,我使用了Canvas
并在其上放置了控件。
应用程序中显示的此类抽奖示例可在此处找到: http : //free0.hiboox.com/images/1610/d82e0b7cc3521071ede601d3542c7bc5.png
它适用于简单图形,但是我也希望能够绘制非常大的图形(数百个节点)。 当我尝试绘制一个非常大的图形时,需要花费很多时间进行渲染。
我的问题是代码根本没有优化,我只是希望它能工作。 到目前为止,我一方面拥有一个Canvas,另一方面拥有多个控件。 实际上,圆和线是在集合中列出的,对于这些集合中的每个项目,我都使用ControlTemplate
,定义一个红色圆圈,一个黑色圆圈,一条线等。
这是一个示例图圆的定义:
<!--
STYLE : DISPLAY DATA NODE
-->
<Style TargetType="{x:Type flow.elements:DisplayNode}">
<Setter Property="Canvas.Left" Value="{Binding X, RelativeSource={RelativeSource Self}}" />
<Setter Property="Canvas.Top" Value="{Binding Y, RelativeSource={RelativeSource Self}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type flow.elements:DisplayNode}">
<!--TEMPLATE-->
<Grid x:Name="grid" Margin="-30,-30,0,0">
<Ellipse x:Name="selectionEllipse" StrokeThickness="0" Width="60"
Height="60" Opacity="0" IsHitTestVisible="False">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="Black" Offset="0.398" />
<GradientStop Offset="1" />
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Stroke="Black" Width="30" Height="30" x:Name="ellipse">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="0" Color="White" />
<GradientStop Offset="1.5" Color="LightGray" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<TextBlock x:Name="tblock"
Text="{Binding NodeName, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Foreground="Black" VerticalAlignment="Center"
HorizontalAlignment="Center" FontSize="10.667" />
</Grid>
<!--TRIGGERS-->
<ControlTemplate.Triggers>
<!--DATAINPUT-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="SkinMode" Value="NODETYPE" />
<Condition Property="NodeType" Value="DATAINPUT" />
</MultiTrigger.Conditions>
<Setter TargetName="tblock" Property="Foreground" Value="White" />
<Setter TargetName="ellipse" Property="Fill">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="-0.5" Color="White" />
<GradientStop Offset="1" Color="Black" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
<!--DATAOUTPUT-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="SkinMode" Value="NODETYPE" />
<Condition Property="NodeType" Value="DATAOUTPUT" />
</MultiTrigger.Conditions>
<Setter TargetName="tblock" Property="Foreground" Value="White" />
<Setter TargetName="ellipse" Property="Fill">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1">
<GradientStop Offset="-0.5" Color="White" />
<GradientStop Offset="1" Color="Black" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
....... THERE IS A TOTAL OF 7 MULTITRIGGERS .......
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
同样,使用“ Line
控件”绘制Line
。
<!--
STYLE : DISPLAY LINK
-->
<Style TargetType="{x:Type flow.elements:DisplayLink}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type flow.elements:DisplayLink}">
<!--TEMPLATE-->
<Line X1="{Binding X1, RelativeSource={RelativeSource TemplatedParent}}"
X2="{Binding X2, RelativeSource={RelativeSource TemplatedParent}}"
Y1="{Binding Y1, RelativeSource={RelativeSource TemplatedParent}}"
Y2="{Binding Y2, RelativeSource={RelativeSource TemplatedParent}}"
Stroke="Gray" StrokeThickness="2" x:Name="line" />
<!--TRIGGERS-->
<ControlTemplate.Triggers>
<!--BRANCH : ASSERTION-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="SkinMode" Value="BRANCHTYPE" />
<Condition Property="BranchType" Value="ASSERTION" />
</MultiTrigger.Conditions>
<Setter TargetName="line" Property="Stroke" Value="#E0E0E0" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
因此,我需要您的建议。 如何彻底改善渲染性能? 我应该在自己的ControlTemplate中定义每个MultiTrigger
圆的渲染可能性吗? 有更好的线条绘制技术吗?
我应该打开一个DrawingContext
并在一个控件中绘制所有内容,而不是拥有数百个控件吗?
我经常看到这一点,而且我总是有相同的答案。 这就是构建图形时发生的情况。 不要建立图形, 绘制图形。 换句话说,不要在应用程序数据之上创建大量的数据结构(大量控件)。 而是有一个Paint事件处理程序,可以通过DrawLine , DrawEllipse等进行绘制 。
这是“ 数据停止者”格言的特定实例。
仅当您知道需要能够响应绘制的对象上的鼠标接触时,才有意义制作某些类型的对象,即使这样,也可能没有。
如果渲染由于您有太多对象而导致大量闪烁,则渲染它们将花费大量时间,请尝试绘制到内存位图,然后将其复制到屏幕。 确保预涂事件不会清除屏幕。 那就是我所做的,而且看起来总是很好。
补充:我意识到您不能总是避免管理很多控件,因此我有相应的策略。 例如,我经常必须编写UI对话框,其中控件的内容随基础应用程序数据的变化而动态变化很多。 我发现处理该问题的标准众所周知的标准方法很粗糙,难以编写代码且容易出错。 幸运的是,我偶然发现了我认为更好的方法,即动态对话框 。 我不是说这是为了胆小的人。 我确实声称它节省了代码的数量级,像时钟一样工作,并且从管理,绑定和所有此类事件的管理中解放出来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.