WPF-IScrollInfo实现

WPF-IScrollInfo实现,wpf,scroll,itemscontrol,measureoverride,arrangeoverride,Wpf,Scroll,Itemscontrol,Measureoverride,Arrangeoverride,问题是:一个窗口有一个ItemsControl和一些项目(比如矩形)。 窗口设置了最小宽度和最小高度(如300) 我需要,当我调整窗口大小,如果矩形没有足够的空间来显示,以显示在2列。 如果在2列中仍然没有足够的空间显示滚动查看器 我所尝试的: 1.创建扩展项控件: My ItemsControl具有作为ItemsPanelTemplate的扩展网格: 公共类MyGrid:Grid,IScrollInfo { ..IScrollInfo实现 } 我使用这个网格的想法是,当ItemsCon

问题是:一个窗口有一个ItemsControl和一些项目(比如矩形)。 窗口设置了最小宽度和最小高度(如300) 我需要,当我调整窗口大小,如果矩形没有足够的空间来显示,以显示在2列。 如果在2列中仍然没有足够的空间显示滚动查看器

我所尝试的: 1.创建扩展项控件:


My ItemsControl具有作为ItemsPanelTemplate的扩展网格:

公共类MyGrid:Grid,IScrollInfo { ..IScrollInfo实现 }

我使用这个网格的想法是,当ItemsControl将PrepareContainerForItemOverride()时,我可以使用它将项目拆分为两列

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

这件事已经结束了…如果你们中有人有线索,请告诉我。
谢谢你们

在我看来,您所需要的只是
ItemsControl
中的另一个面板。也许您可以使用内置的
WrapPanel
,但您也可以编写自己的:

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

在我看来,您所需要的只是
项目控件中的一个不同面板。也许您可以使用内置的
WrapPanel
,但您也可以编写自己的:

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

如果有人需要,我想与大家分享我采用的解决方案

为了避免实现IScrollInfo,我将ItemsControl更改为ListBox控件。所以,我还是决定放弃。 在Arrange中,我计算第一列的项目高度,并在GridPanel中排列项目。我之所以使用dispatcher,是因为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;
    }

受保护的替代尺寸排列替代(尺寸最终化)
{
大小arrangeSize=base.ArrangeOverride(最终化);
lastItemInFirstColumn=-1;
双总高度=0;
DispatcherPriority p=ScrollViewer.IsArrangeValid?DispatcherPriority.Normal:DispatcherPriority.Input;
如果(o!=null)
o、 中止();
o=调度程序。开始运行(p,(操作)(()=>
{
double fitHeight=ScrollViewer.ActualHeight;
foreach(此.InternalChildren中的UIElement子元素)
{
if(总高度+child.DesiredSize.Height{o=null;};
返回安排大小;
}

如果有人需要,我想与大家分享我采用的解决方案

为了避免实现IScrollInfo,我将ItemsControl更改为ListBox控件。所以,我还是决定放弃。 在Arrange中,我计算第一列的项目高度,并在GridPanel中排列项目。我之所以使用dispatcher,是因为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;
    }

受保护的替代尺寸排列替代(尺寸最终化)
{
大小arrangeSize=base.ArrangeOverride(最终化);
lastItemInFirstColumn=-1;
双总高度=0;
DispatcherPriority p=ScrollViewer.IsArrangeValid?DispatcherPriority.Normal:DispatcherPriority.Input;
如果(o!=null)
o、 中止();
o=调度程序。开始运行(p,(操作)(()=>
{
double fitHeight=ScrollViewer.ActualHeight;
foreach(此.InternalChildren中的UIElement子元素)
{
if(总高度+child.DesiredSize.Height