VirtualizingPanel останавливает работу ScrollViewer в Viewbox - PullRequest
0 голосов
/ 08 мая 2018

У меня есть простая пользовательская панель, размещенная в ItemsPanel из ItemsControl. Template из ItemsControl обновляется, чтобы окружить ItemsPresenter Viewbox и ScrollViewer. Вот код XAML:

<ItemsControl ItemsSource="{Binding Buttons, RelativeSource={RelativeSource 
    AncestorType={x:Type Local:MainWindow}}}" 
    ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
    ScrollViewer.VerticalScrollBarVisibility="Visible" 
    ScrollViewer.CanContentScroll="True">
    <ItemsControl.Template>
        <ControlTemplate TargetType="{x:Type ItemsControl}">
            <ScrollViewer CanContentScroll="True">
                <Viewbox Stretch="UniformToFill">
                    <ItemsPresenter />
                </Viewbox>
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Local:TestPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Height="250" Width="250" HorizontalAlignment="Center" 
                Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

А Panel:

public class TestPanel : Panel
{
    protected override Size MeasureOverride(Size availableSize)
    {
        var desiredSize = new Size();
        var layoutSlotSize = availableSize;

        layoutSlotSize.Height = double.PositiveInfinity;
        for (int i = 0, count = InternalChildren.Count; i < count; ++i)
        {
            UIElement child = InternalChildren[i];
            if (child == null) continue;
            child.Measure(layoutSlotSize);
            var childDesiredSize = child.DesiredSize;
            desiredSize.Width = Math.Max(desiredSize.Width, childDesiredSize.Width);
            desiredSize.Height += childDesiredSize.Height;
        }
        return desiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        double verticalOffset = 0;
        for (int i = 0, count = InternalChildren.Count; i < count; ++i)
        {
            UIElement child = InternalChildren[i];
            if (child == null) continue;
            child.Arrange(new Rect(0, verticalOffset, child.DesiredSize.Width, 
                child.DesiredSize.Height));
            verticalOffset += child.DesiredSize.Height;
        }
        return base.ArrangeOverride(finalSize);
    }
}

И, наконец, MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Buttons = new ObservableCollection<string>();
        IEnumerable<int> characterCodes = Enumerable.Range(65, 26);
        foreach (int characterCode in characterCodes) 
            Buttons.Add(((char)characterCode).ToString().ToUpper());
    }

    public static readonly DependencyProperty ButtonsProperty = 
        DependencyProperty.Register(nameof(Buttons), typeof(ObservableCollection<string>), 
        typeof(MainWindow), null);

    public ObservableCollection<string> Buttons
    {
        get { return (ObservableCollection<string>)GetValue(ButtonsProperty); }
        set { SetValue(ButtonsProperty, value); }
    }
}

Это все работает как положено ... пока все хорошо. Проблема заключается в том, что я изменяю базовый класс с Panel на VirtualizingPanel, что мне нужно сделать для виртуализации данных (а не данных этого примера кнопки). После смены базового класса панель сразу перестает работать. Я полностью осведомлен о том, как виртуализировать данные в панели ... У меня есть рабочий пример этого. Моя проблема, когда я хочу добавить Viewbox внутри ScrollViewer.

Обратите внимание, что этот XAML будет нормально работать с обычными Panel или StackPanel, но как только я изменю его на VirtualizingPanel, он перестает работать (ничего не отображается, а свойство InternalChildren содержит нет элементов). Кто-нибудь может пролить свет на эту проблему для меня, пожалуйста?

1 Ответ

0 голосов
/ 09 мая 2018

Я до сих пор не знаю, почему VirtualizingPanel не работает внутри ViewBox внутри ScrollViewer, но я обнаружил, что если я вместо этого расширяю класс VirtualizingStackPanel в своей панели, все работает как положено.

Таким образом, решение для тех, кому требуется штабелировать виртуализированные элементы, состоит в расширении класса VirtualizingStackPanel. Прошу прощения у тех, кому нужны другие виды детской организации, но у меня нет ответа, если только вы не удалите Viewbox.

Я был бы более чем рад получить дополнительную информацию по этому вопросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...