我正在尝试在WPF中创建自定义控件以显示game of go的游戏树(请参阅here了解它的样子)。我或多或少地让它在设置节点时工作,但我发现的一个问题是,当节点数量大于约时,它开始变得非常慢(在滚动查看器中) 30.由于平均每场比赛由大约200次移动组成(更不用说其他分支球员可能会分叉),这对于任何逼真的比赛来说都是一个相当大的问题。
目前,我正在为游戏节点使用单独的用户控件(每个都是一个带有阴影位图效果的椭圆和一些文本注释)和树中弧线的简单线条,所有这些都完全位于画布。
布局算法不是一个问题,因为这只需要在创建新分支时执行(否则可以直接在其父级下添加节点,因此不需要重新定位其他节点)。主要的问题是对画布及其元素的任何操作都非常缓慢,大概只是因为它有多少个孩子。随着树的宽度和复杂性的增加,它显然会变慢,因为有更多的弧和节点。
我的问题:以这样的方式绘制像这样的大型/复杂结构的正确方法是什么?它不会随着它的增长而变得太慢?
修改:这与my other question。
相关编辑:以下是我用于节点的用户控件的标记:
<UserControl x:Class="Go.UI.GameNodeMarker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Go.UI"
xmlns:wpftools="clr-namespace:WpfTools.Extensions;assembly=WpfTools"
x:Name="_This">
<UserControl.Resources>
<!-- Some brushes, resources, etc. are omitted -->
<Style x:Key="StoneStyle" TargetType="{x:Type Ellipse}">
<Setter Property="StrokeThickness" Value="0"/>
<Setter Property="BitmapEffect" Value="{StaticResource StoneEffect}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=_This, Path=StoneColour}" Value="Black">
<Setter Property="Fill" Value="{StaticResource BlackStoneBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=_This, Path=StoneColour}" Value="White">
<Setter Property="Fill" Value="{StaticResource WhiteStoneBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=_This, Path=IsEmpty}" Value="True">
<Setter Property="Fill" Value="{StaticResource EmptyBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<Ellipse Style="{StaticResource StoneStyle}"/>
<TextBlock Text="{Binding ElementName=_This, Path=Text}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Medium"/>
</Grid>
</UserControl>
将这些动态添加到画布中以绘制树。
答案 0 :(得分:8)
渲染控件实际上非常昂贵。如果您在客户区域中进行自定义绘图(自己绘制项目而不是放置控件),您将看到性能显着提高。
这是我在做这类工作时的经验。如果您需要十几个控件,请选择所有者。
顺便说一下,不要让自定义绘图吓倒你。它并不比动态放置控件复杂得多。
答案 1 :(得分:1)
我自己就是一个四维游戏玩家:)你可能想要创建一个棋盘的位图,然后重新绘制已经改变的部分。
答案 2 :(得分:0)
我知道这可能不会真正回答这个问题,但我认为值得指出。
WPF4将在不久的将来推出,它将支持缓存元素的图形,在许多情况下不需要重绘。在你想要利用它的元素上添加几个属性,你就可以了。如果您最终使用此功能,请尝试避免不必要的动画。如果屏幕上的每个元素都需要在每一帧上重绘,那么缓存就没有意义了。翻转动画会很好。
答案 3 :(得分:0)
我不知道你是否会喜欢我的建议,因为它看起来很难看,但你可以尝试通过以下方式关闭抗锯齿:
将当前Window的RenderOptions.EdgeMode设置为“Unspecified”(无抗锯齿)
你应该获得更好的表现,但是某种粗略的绘画。
祝你好运! 埃里克