WPF виртуализирует большие предметы - PullRequest
2 голосов
/ 04 апреля 2011

Я связываю довольно большую коллекцию предметов с ItemsControl. ItemTemplate ItemsControl установлен на пользовательский пользовательский контроль, отображающий данные. ItemControl виртуализирован.

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

Есть ли способ обойти это поведение и при этом использовать виртуализацию?

Ответы [ 2 ]

1 голос
/ 04 апреля 2011

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

Вы можете создать свою собственную панель (производную от VirtualizingPanel), которая не имеет этого ограничения. Это не просто, но это стоит результатов!

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

1 голос
/ 04 апреля 2011

Имеет ли ScrollViewer вашего ItemsControl набор прокрутки контента?

Редактировать 2: Как и предполагал Дэн, появляется, как только вы пытаетесь получить плавную прокрутку, вы теряете виртуализацию. Я не уверен, каковы ваши требования, но возможный обходной путь может быть что-то вроде следующего:

<Window x:Class="TestApp11.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        mc:Ignorable="d"
    xmlns:l="clr-namespace:TestApp11"
    Title="Window1" Height="200" Width="200">
    <Grid>
        <ItemsControl>
            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type ListBoxItem}">
                    <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" MaxHeight="160">
                        <Border Height="200" Width="140" BorderBrush="Red" BorderThickness="10" Margin="1" Background="Blue" />
                    </ScrollViewer>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel VirtualizingStackPanel.VirtualizationMode="Recycling" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
        </ItemsControl>
    </Grid>
</Window>

По сути, вы можете иметь ItemTemplate обернуть ваши элементы UserControl внутри ScrollViewer. Я не показывал это в моем примере, но вы можете привязать MaxHeight ScrollViewer (внутри ItemTemplate) к высоте вашей видимой области, и тогда вертикальная полоса прокрутки будет отображаться, только если ваш UserControl слишком большой поместиться на экране.

Я вижу, где это может быть слишком уродливым решением, чтобы предложить клиенту, однако, в этом случае я думаю, что единственный вариант - пойти по пути, предложенному Дэном.

...