WPF - IScrollInfo 实现

发布于 2024-12-15 00:51:49 字数 1542 浏览 4 评论 0原文

问题:一个带有 ItemsControl 和一些项目(比如说矩形)的窗口。 窗口已设置 MinWidth 和 MinHeight(例如 300) 当我调整窗口大小时,如果矩形没有足够的空间来显示以显示在两列中,我需要这样做。 如果两列中仍然没有足够的空间来显示滚动查看器。

我尝试过的: 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 扩展网格:

public class MyGrid : Grid, IScrollInfo { ....IScrollInfo 实现 我使用这个网格,

认为当 ItemsControl 将PrepareContainerForItemOverride() 时,我可以使用它来将 Items 分成两列。

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

这个问题已经结束了...如果你们中的一些人有的话,请给我一个线索。 谢谢你们!

The problem: An Window that has an ItemsControl with some items(let's say Rectangles).
The window has MinWidth and MinHeight setted(eg. 300)
I need that when I resize window if the rectangles has not enough space to be displayed to be displayed in 2 columns.
And if in 2 columns still does not have enought space to show a scroll viewer.

What I've tried:
1. Create an extended 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>

My ItemsControl has as ItemsPanelTemplate an Extended grid:

public class MyGrid : Grid, IScrollInfo
{
....IScrollInfo implementation
}

I use this grid thinking that when ItemsControl will PrepareContainerForItemOverride() I can use this to split the Items in two columns.

The ideea is "taken" from a conference....but I no not know what to do next...
I have questions like:
when I override Measure and Arrange for data grid I set the position of the items in DataGrid, but then it is called PrepareContainerForItemOverride()...then what? I should compute the no of rows I should make? but if then I resize again the window...PrepareContainerForItemOverride() won't be called ...

It is over me this issue...please give me a clue if some of you have one.
Thank you guys!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

洋洋洒洒 2024-12-22 00:51:49

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

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

It sounds to me like all you need is a different panel in your ItemsControl. It may be that you'd get away with using the built-in WrapPanel, but you could also write your own:

<ItemsControl ...>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- put whatever panel that encapsulates your layout logic here, possibly your own -->
            <WrapPanel/>
        </ItemsPanelTemplate>
    <ItemsControl.ItemsPanel>
</ItemsControl>
思念绕指尖 2024-12-22 00:51:49

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

为了避免 IScrollInfo 的实现,我将 ItemsControl 更改为 ListBox 控件。所以我仍然要覆盖排列。
在排列中,我计算第一列的项目高度,并在 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;
    }

I wanted to share the solution I took...if anyone needs it.

To avoid the implementation of IScrollInfo I changed ItemsControl with ListBox control. So it remains that I override Arrange.
In Arrange I calculate my first column's items height and I arrange the Items in GridPanel. I use the dispatcher because the scrollViewer arrange is not always VALID and I am counting on it to get the visible height.

<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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文