Производительность рисования WPF с большим количеством элементов - PullRequest
4 голосов
/ 13 января 2010

Я пытаюсь создать пользовательский элемент управления в 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 ]

8 голосов
/ 13 января 2010

Визуализация элементов управления на самом деле довольно дорогая. Если вы выполняете нестандартное рисование (рисуете элементы самостоятельно, а не размещаете элементы управления) в клиентской области, вы увидите, что ваша производительность резко возрастет.

Это был мой опыт снова и снова при выполнении этого вида работы. Если вам нужно более десятка элементов управления, обратитесь за владельцем.

Кстати, не позволяйте собственному рисунку запугивать вас. Это не намного сложнее, чем динамическое размещение элементов управления.

Ссылка на образец чертежа WPF

1 голос
/ 13 января 2010

Я сам играю в 4-D go :) Вы можете создать битовую карту доски и просто перерисовать измененную часть.

0 голосов
/ 09 марта 2012

Не знаю, понравится ли вам мое предложение, потому что оно будет выглядеть уродливо, но вы можете попробовать отключить сглаживание:

Установите для RenderOptions.EdgeMode для текущего окна значение «Не указано» (без сглаживания)

Вы должны получить лучшую производительность, но какой-то грубый рисунок.

Удачи! Eric

0 голосов
/ 13 января 2010

Я знаю, что это не может действительно ответить на вопрос, но я думаю, что на это стоит обратить внимание.

WPF4 появится в ближайшем будущем и будет поддерживать кэширование графики элемента, во многих случаях делая перерисовку ненужной. Добавьте пару атрибутов к элементам, которыми вы хотите воспользоваться, и все готово. Если вы в конечном итоге используете это, попробуйте избежать ненужных анимаций. Нет смысла кэшировать вещи, если каждый элемент на экране требует перерисовки каждого кадра. Анимации ролловера будут в порядке.

...