Виснет Canvas при прокрутке

302
09 декабря 2016, 08:53

Всем привет! И снова я в продолжении этого вопроса, который оброс новыми. Надеюсь в последний раз.

В решении задачи нашлось два способа вывода большого числа элементов в Canvas.

Первый:

<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" CanContentScroll="True">
            <ItemsControl>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas Width="1000" Height="1000"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Left" Value="{Binding X}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                    </Style>
                </ItemsControl.ItemContainerStyle>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Rectangle Width="{Binding Pattern.RectSize, Source={StaticResource Locator}}" Height="{Binding Pattern.RectSize, Source={StaticResource Locator}}" Fill="{Binding Fill}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
</ScrollViewer>

Второй(большое спасибо @VladD):

public class SchemeCanvas: Panel
{
    ...
    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);
        ...
    }
}

+

<ScrollViewer>
    <controls:SchemeCanvas/>
</ScrollViewer>

НО. В первом способе, загрузка данных происходит очень долго, вешая при этом UI, но прокрутка работает отлично. Во втором способе изображение появляется почти мгновенно, но прокрутка тормозит.

Как я понимаю, первый способ предполагает AddChild в Canvas, а второй отрисовку коллекции целиком.

Как решить эту(-и) проблему(-ы)? Как объединить скорость загрузки и плавность прокрутки?

ZoomableCanvas и VirtualizedCanvas из блога msdn мне не помогли. Подключал все по примерам. ZoomableCanvas дает тот же результат, VirtualizedCanvas тормозит совсем и приходится создавать еще кучу кода для приведения своего типа в нужный.

P.S.: от OpenGL отказался в сторону простоты и печати.

Answer 1

Отвечу сам на свой вопрос. Решил пойти следующим путем: Завернул в Canvas(который сам находится в ScrollViewr) три элемента: Imageи два Canvas (или что-нибудь FramworkElement). В Image передаю Bitmap, растянутый LayoutTransform до нужного размера на:

double Scale = BlockSize/PixelSaze

где BlockSize - размер сетки и отображаемых пикселей, PixelSize - размер фильтра пикселизации.

Размер Canvas делаю так:

Width = Scale * Bitmap.Width // + Padding, если нужны поля
Height = Scale * Bitmap.Height // + Padding, если нужны поля

Такие же размеры остальным слоям. И с помощью BlockSize задаю размер сетки.

В третий слой в OnRender вывожу буквы. Тут приходится подключать CacheMode. Работает гладко. Печатается хорошо, но с одной оговоркой.

READ ALSO
Ошибка десериализации Json

Ошибка десериализации Json

Есть Json следующего вида

316
ObservableCollection в Backgroundworker

ObservableCollection в Backgroundworker

Есть метод поиска файлов:

262
Замена по регулярке

Замена по регулярке

Допустим, имеется текст text1(text2)text2 нужно получить text1 (text2) text2

287