5

WPF でカスタム コントロールを作成して、囲碁のゲーム ツリーを表示しようとしています(外観については、こちらを参照してください)。ノードのレイアウトは多かれ少なかれ機能していますが、ノードの数がおよそ30. 囲碁の平均的なゲームは約 200 の手で構成されているため (プレーヤーが分岐する可能性のある他の分岐は言うまでもありません)、これは現実的なゲームではかなり大きな問題になるでしょう。

現在、私はゲーム ノードに個々のユーザー コントロール (それぞれが影のビットマップ効果といくつかのテキスト注釈が付いた楕円) とツリー内の円弧に単純な線を使用しています。これらはすべてキャンバスに絶対的に配置されています。

レイアウト アルゴリズムは、新しいブランチが作成されたときにのみ実行する必要があるため、それほど問題ではありません (それ以外の場合、ノードはその親のすぐ下に追加できるため、他のノードを再配置する必要はありません)。主な問題は単純に、このキャンバスとその要素のあらゆる種類の操作が非常に遅いことです。これはおそらく、キャンバスに含まれる子の数が原因であると考えられます。ノードだけでなくアークも多いため、ツリーの幅と複雑さが増すにつれて、明らかに遅くなります。

私の質問:このような大規模/複雑な構造を、成長するにつれてレンダリングが遅すぎないように描画する適切な方法は何ですか?

編集:これは私の他の質問に関連しています。

編集:ノードに使用しているユーザーコントロールのマークアップは次のとおりです。

<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>

これらは、ツリーを描画するためにキャンバスに動的に追加されています。

4

4 に答える 4

9

コントロールのレンダリングは、実際には非常にコストがかかります。クライアント領域でカスタム描画 (コントロールを配置する代わりに自分で項目を描画する) を行うと、パフォーマンスが劇的に向上することがわかります。

これは、この種の仕事をしているときに何度も経験しました。ダース以上のコントロールが必要な場合は、所有者描画を使用してください。

ところで、カスタム ドローイングに惑わされないでください。コントロールを動的に配置するよりもそれほど複雑ではありません。

カスタム WPF 描画サンプルへのリンク

于 2010-01-12T23:41:21.347 に答える
1

私自身は4Dプロ棋士です:)ボードのビットマップを作成して、変更された部分を再描画することをお勧めします。

于 2010-01-12T23:52:47.487 に答える
1

見た目が醜いので、私の提案が気に入るかどうかはわかりませんが、次の方法でアンチエイリアスをオフにすることができます。

現在のウィンドウのRenderOptions.EdgeModeを「未指定」(アンチエイリアスなし)に設定します

パフォーマンスは向上するはずですが、ある種の粗い描画が得られます。

幸運を !エリック

于 2012-03-08T21:31:12.027 に答える
0

これは実際には質問に答えないかもしれませんが、指摘する価値があると思います。

WPF4は近い将来登場し、要素のグラフィックのキャッシュをサポートするため、多くの場合、再描画は不要になります。これを利用したい要素にいくつかの属性を追加すれば、準備は完了です。これを使用することになった場合は、不要なアニメーションを避けるようにしてください。画面上のすべての要素がすべてのフレームで再描画する必要がある場合は、キャッシュしても意味がありません。ロールオーバーアニメーションは問題ありません。

于 2010-01-13T17:32:15.627 に答える