繁体   English   中英

WPF,如何优化线和圆图?

[英]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事件处理程序,可以通过DrawLineDrawEllipse等进行绘制

这是“ 数据停止者”格言的特定实例。

仅当您知道需要能够响应绘制的对象上的鼠标接触时,才有意义制作某些类型的对象,即使这样,也可能没有。

如果渲染由于您有太多对象而导致大量闪烁,则渲染它们将花费大量时间,请尝试绘制到内存位图,然后将其复制到屏幕。 确保预涂事件不会清除屏幕。 那就是我所做的,而且看起来总是很好。

补充:我意识到您不能总是避免管理很多控件,因此我有相应的策略。 例如,我经常必须编写UI对话框,其中控件的内容随基础应用程序数据的变化而动态变化很多。 我发现处理该问题的标准众所周知的标准方法很粗糙,难以编写代码且容易出错。 幸运的是,我偶然发现了我认为更好的方法,即动态对话框 我不是说这是为了胆小的人。 我确实声称它节省了代码的数量级,像时钟一样工作,并且从管理,绑定和所有此类事件的管理中解放出来。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM