未调整大小以填充可用空间的项目

时间:2013-12-03 10:59:27

标签: wpf xaml

我正在开发一个WPF应用程序,我有一个ListBox

    <ListBox Grid.Column="1" ItemsSource="{Binding MyUserControls}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
             HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True" Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

当用户点击按钮时,我将UserControl实例添加到MyUserControls(ObservableCollection)。 Listbox位于我主窗口的Grid中。我需要的是当添加越来越多的用户控件时,他们应该动态调整大小到最小宽度,然后添加到下一行。但我无法做到这一点。我能够获得wrappanel行为,但元素没有调整大小(我必须设置宽度属性,以确保连续只有3个用户控件)。即使添加了一个用户控件,它也不会填满整个网格。

如果您需要更多信息,请告诉我。

2 个答案:

答案 0 :(得分:2)

互联网上已经有很多漂亮的东西可以告诉你如何拥有这样的WrapPanel。这是一个:

public class ElasticWrapPanel : Panel
{
    /// <summary>
    /// Identifies the <see cref="DesiredColumnWidth"/> dependency property. 
    /// </summary>
    internal static readonly DependencyProperty DesiredColumnWidthProperty = DependencyProperty.Register("DesiredColumnWidth", typeof(double), typeof(ElasticWrapPanel), new PropertyMetadata(100d, new PropertyChangedCallback(OnDesiredColumnWidthChanged)));

    private int _columns;

    protected override Size MeasureOverride(Size availableSize)
    {
        _columns = (int) (availableSize.Width / DesiredColumnWidth);

        foreach (UIElement item in this.Children)
        {
            item.Measure(availableSize);
        }

        return base.MeasureOverride(availableSize);
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        if (_columns != 0)
        {
            double columnWidth = Math.Floor(finalSize.Width/_columns);

            double top = 0;
            double rowHeight = 0;
            int column = 0;
            foreach (UIElement item in this.Children)
            {
                item.Arrange(new Rect(columnWidth * column, top, columnWidth, item.DesiredSize.Height));                    
                column++;
                rowHeight = Math.Max(rowHeight, item.DesiredSize.Height);

                if (column == _columns)
                {
                    column = 0;                        
                    top += rowHeight;
                    rowHeight = 0;
                }
            }
        }

        return base.ArrangeOverride(finalSize);
    }

    private static void OnDesiredColumnWidthChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var panel = (ElasticWrapPanel)obj;
        panel.InvalidateMeasure();
        panel.InvalidateArrange();
    }

    public double DesiredColumnWidth
    {
        get
        {
            return (double)GetValue(DesiredColumnWidthProperty);
        }

        set
        {
            SetValue(DesiredColumnWidthProperty, value);
        }
    }
}

在xaml中,您将拥有以下内容:

   <c:ElasticWrapPanel DesiredColumnWidth="200">
        <Button Content="Item1" />
        <Button Content="Item2" />
        <Button Content="Item3" />
        <Button Content="Item4" />
        <Button Content="Item5" />
        <Button Content="Item6" />
    </c:ElasticWrapPanel>

答案 1 :(得分:1)

您描述的行为是WrapPanel的正常行为。如果您希望Panel自动填充每行的空间,则需要为自己创建自定义Panel。如果你擅长数学,那么创建一个自定义Panel并不像看起来那么困难...只有两种方法可以覆盖你计算每个元素的大小。

您可以通过以下链接找到热门来创建自定义Panel

How to create a Custom Layout Panel in WPF
Creating Custom Panels In WPF
Custom Panel Elements section of Panels Overview