WPF - реализация IScrollInfo - PullRequest
       21

WPF - реализация IScrollInfo

2 голосов
/ 11 ноября 2011

Проблема: окно, в котором есть ItemsControl с некоторыми элементами (скажем, Rectangles).В окне установлены MinWidth и MinHeight (например, 300). Мне нужно это, когда я изменяю размер окна, если у прямоугольников недостаточно места для отображения в 2 столбцах.И если в 2 столбцах все еще не хватает места для отображения средства просмотра прокрутки.

Что я пробовал: 1. Создать расширенный элемент ItemsControl:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <local:MyGrid IsItemsHost="True" x:Name="PART_ItemsPanel" Initialized="OnItemsPanelInitialized" CanVerticallyScroll="True" CanHorizontallyScroll="True">
            <local:MyGrid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </local:MyGrid.ColumnDefinitions>
            <local:MyGrid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </local:MyGrid.RowDefinitions>
        </local:MyGrid>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Мой ItemsControl имеет в качестве ItemsPanelTemplate расширенную сетку:

открытый класс MyGrid: Grid, IScrollInfo {.... реализация IScrollInfo}

Я использую эту сетку, полагая, что когда ItemsControl будет PrepareContainerForItemOverride (), яможно использовать это, чтобы разделить элементы в два столбца.

Идея "взята" из конференции .... но я не знаю, что делать дальше ... У меня есть вопросы, такие как: когда я переопределитьИзмерение и расположение для сетки данных Я устанавливаю положение элементов в DataGrid, но тогда он называется PrepareContainerForItemOverride () ... и что тогда?Я должен вычислить количество строк, которые я должен сделать?но если затем я снова изменю размер окна ... PrepareContainerForItemOverride () не будет вызываться ...

Это проблема для меня ... пожалуйста, дайте мне подсказку, если у некоторых из вас есть такая.Спасибо, ребята!

Ответы [ 2 ]

0 голосов
/ 16 ноября 2011

Я хотел бы поделиться решением, которое я принял ... если кому-то это нужно.

Чтобы избежать реализации IScrollInfo, я изменил ItemsControl с элементом управления ListBox. Так что осталось, что я переопределяю Arrange. В Arrange я вычисляю высоту элементов моего первого столбца и располагаю элементы в GridPanel. Я использую диспетчер, потому что расположение scrollViewer не всегда ДЕЙСТВИТЕЛЬНО, и я рассчитываю на него, чтобы получить видимую высоту.

<ListBox x:Uid="allListBox" x:Name="adminListBoxControl" ItemTemplate ="{DynamicResource LinkButtonItemTemplate}" Margin="15" BorderBrush="Transparent" Background="Transparent">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <local:GridPanel>
                        <local:GridPanel.ColumnDefinitions>
                            <ColumnDefinition Width="0.45*"/>
                            <ColumnDefinition Width="0.45*"/>
                            <ColumnDefinition Width="0.1*"/>
                        </local:GridPanel.ColumnDefinitions>
                        <local:GridPanel.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </local:GridPanel.RowDefinitions>
                    </local:GridPanel>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>

protected override Size ArrangeOverride(Size finalSize)
    {
       Size arrangeSize = base.ArrangeOverride(finalSize);

        lastItemInFirstColumn = -1;
        double totalHeight = 0;

        DispatcherPriority p = ScrollViewer.IsArrangeValid ? DispatcherPriority.Normal : DispatcherPriority.Input;
        if (o != null)
            o.Abort();

        o = Dispatcher.BeginInvoke(p, (Action)(() =>
        {
            double fitHeight = ScrollViewer.ActualHeight;
            foreach (UIElement child in this.InternalChildren)
            {
                if (totalHeight + child.DesiredSize.Height < fitHeight)
                {
                    totalHeight += child.DesiredSize.Height;
                    lastItemInFirstColumn++;
                }
                else
                {
                    if (lastItemInFirstColumn + 1 < InternalChildren.Count - (lastItemInFirstColumn + 1))
                        lastItemInFirstColumn++;
                    break;
                }
            }

            //set items positions
            ArrangeItemsInGrid();
        }));

        o.Completed += (s, e) => { o = null; };
        return arrangeSize;
    }
0 голосов
/ 11 ноября 2011

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

<ItemsControl ...>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- put whatever panel that encapsulates your layout logic here, possibly your own -->
            <WrapPanel/>
        </ItemsPanelTemplate>
    <ItemsControl.ItemsPanel>
</ItemsControl>
...