【问题标题】:WPF - IScrollInfo implementationWPF - IScrollInfo 实现
【发布时间】:2011-12-26 15:10:03
【问题描述】:

问题:一个带有 ItemsControl 和一些项目的窗口(比如说矩形)。 窗口设置了 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() 时,我可以使用它来将项目分成两列。

这个想法是从一次会议中“获取”的......但我不知道下一步该做什么...... 我有这样的问题: 当我为数据网格覆盖 Measure 和 Arrange 时,我在 DataGrid 中设置了项目的位置,但后来它被称为 PrepareContainerForItemOverride()...然后呢?我应该计算我应该做的行数?但是如果然后我再次调整窗口大小... PrepareContainerForItemOverride() 将不会被调用...

这个问题已经解决了...如果你们中的一些人有一个线索,请给我一个线索。 谢谢各位!

【问题讨论】:

    标签: wpf scroll itemscontrol measureoverride arrangeoverride


    【解决方案1】:

    我想分享我采取的解决方案……如果有人需要的话。

    为了避免 IScrollInfo 的实现,我将 ItemsControl 更改为 ListBox 控件。所以我仍然要覆盖 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;
        }
    

    【讨论】:

      【解决方案2】:

      在我看来,您只需要在 ItemsControl 中设置一个不同的面板。使用内置的WrapPanel 可能你会侥幸成功,但你也可以自己编写:

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

      【讨论】:

      • 感谢您的回答!我已经尝试过换行面板,但我需要能够将内容放在两列中(如果仍然不适合视口,那么就可以滚动)。我使用了实现 ISCrollViewer 的扩展 Grid,并使用了覆盖的排列、测量……它似乎有效。当(...如果...)我完全实施解决方案时,我会回到这篇文章。
      猜你喜欢
      • 2011-07-04
      • 2010-10-04
      • 1970-01-01
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多