3

我有一个自定义控件 ListBox,我想根据其 ItemsPanel 的大小调整其大小。对于项目面板,我有一个自定义控件 WrapPanel,可以相应地排列项目。正如您在屏幕截图中看到的那样,ListBox 更喜欢根据其父控件或 availableSize 调整自身大小。

然后我尝试制作一个自定义控件网格,它有一个 ItemsSource 属性,可以将项目传递给它的列表框。但这也没有用。当 Grid 排列时,ListBox 将 Arrange,这将导致 Grid 排列等等。

所以我的问题是,如何创建一个具有 ItemsSource 属性和 ItemsPresenter 的自定义控件,该控件根据其子项的内容调整自身大小?

ListBox 自定义控件截图

4

2 回答 2

2

您只需将 ListBox Horizo​​ntalAlignment 设置为 Left,并将 VerticalAlignment 设置为 Top。这应该可以解决问题。

简单的例子:

主窗口.xaml

<Window x:Class="ListBoxFitItemsPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="400">
    <ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Red" HorizontalAlignment="Left" VerticalAlignment="Top" >
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Background="AntiqueWhite" Margin="5" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>

        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
    </ListBox>
</Window>

在此处输入图像描述

编辑:它也适用于绑定场景:

主窗口.xaml

<Window x:Class="ListBoxFitItemsPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ListBoxFitItemsPanel"
        Title="MainWindow" Height="400" Width="400">
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Item}">
            <Rectangle Width="100" Height="100" Fill="LightSlateGray" Stroke="Black" StrokeThickness="1" Margin="5" />
        </DataTemplate>
    </Window.Resources>
    <ListBox ItemsSource="{Binding Items}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Red" HorizontalAlignment="Left" VerticalAlignment="Top" >
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Background="AntiqueWhite" Margin="5" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
</Window>

主窗口.xaml.cs

using System.Collections.Generic;
using System.Windows;

namespace ListBoxFitItemsPanel
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        public IEnumerable<Item> Items
        {
            get
            {
                for (int i = 0; i < 9; i++)
                {
                    yield return new Item();
                }
            }
        }
    }

    public class Item { }
}
于 2013-02-08T15:50:16.913 回答
1

这是我必须做的才能获得我想要的功能。首先我必须创建我的 SquareWrapPanel。这就是魔法发生的地方,并按照我想要的方式安排我的物品。

protected override Size ArrangeOverride(Size finalSize)
    {
        return ArrangeByChildCount(finalSize);
    }

    private Size ArrangeByChildCount(Size finalSize)
    {

        double childWidth = 0;
        double childHeight = 0;


        foreach (UIElement e in Children)
        {
            e.Measure(finalSize);

            childWidth = e.DesiredSize.Width;
            childHeight = e.DesiredSize.Height;
        }

        if (Children.Count > 0)
        {
            int square = (int)Math.Sqrt(Children.Count);


            int rowCount = square + Children.Count % square;
            int columnCount = square;

            double height = rowCount * childHeight;
            double width = columnCount * childWidth;

            Size size = new Size(width, height);
            base.ArrangeOverride(size);
            return size;
        }
        else
        {
            return new Size(300, 300);
        }
    }

然后我创建了一个扩展 ItemsControl 的自定义面板。这样我就可以将一组项目绑定到它。后面的代码中没有任何内容,但这是我必须使用的样式。

    <Style TargetType="{x:Type local:SquareItemsPanel}" BasedOn="{StaticResource {x:Type ItemsControl}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ItemsControl">
                <Border BorderBrush="Black" BorderThickness="2" CornerRadius="4">
                    <Expander x:Name="exp" Header="View">
                        <local:SquareWrapPanel IsItemsHost="True"/>
                    </Expander>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
于 2013-02-26T14:13:36.383 回答