【问题标题】:Making a horizontal list where the items fill to the control's width in Windows 8 XAML?在 Windows 8 XAML 中制作一个水平列表,其中项目填充到控件的宽度?
【发布时间】:2014-06-21 19:27:31
【问题描述】:

我正在制作一个 Windows 8.1 C# 应用程序,其中一行中有一个色块列表。颜色的数量可以改变,我希望色块填满列表控件的宽度。我试过像这样使用 ItemsControl:

<ItemsControl Name="testGrid" HorizontalAlignment="Left" Margin="12,100,0,0" Width="220" Background="Black">
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Rectangle Fill="{Binding}" MinWidth="44" Height="44"/>
    </DataTemplate>
</ItemsControl.ItemTemplate>

我已经尝试了 GridView 和 ListView 以及将 Horizo​​ntalContentAlignment 设置为拉伸的项目样式。主要问题是这些都是垂直列表。我需要一个水平的。

如果我尝试添加 StackPanel,拉伸的项目将停止工作。像这样:

<ItemsControl.ItemsPanel>
   <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal" />
   </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

这是一个示例图像:

我正在使用绑定到列表或可观察集合的项目源。我将如何实现图像中的效果?谢谢

【问题讨论】:

  • 如果它不可用,您可以移植 WPF 的 UniformGrid(并将行设置为 1)
  • UniformGrid 能否在 Win 8.1 环境中工作?这不是他们遗漏的原因吗?
  • 拿UniformGrid的源码自己看吧。我不知道为什么 MS 忽略了它

标签: c# windows-8 windows-runtime winrt-xaml windows-8.1


【解决方案1】:

您需要计算可用宽度并使用它来平均划分所有项目之间的空间。 我在最近的一个项目中完成了您需要的工作,但它是使用ListView 而不是ItemsControl 完成的。 所有的计算代码都在一个继承自Panel的自定义控件中

public class SplitPanel : Panel
{
    protected override Size MeasureOverride(Size availableSize)
    {
        // the final measure size is the available size for the width, and the maximum
        // desired size of our children for the height
        Size finalSize = new Size { Width = availableSize.Width };

        if (this.Children.Count != 0)
            availableSize.Width /= (double)this.Children.Count;

        foreach (var current in this.Children)
        {
            current.Measure(availableSize);

            Size desiredSize = current.DesiredSize;
            finalSize.Height = Math.Max(finalSize.Height, desiredSize.Height);
        }

        // make sure it will works in design time mode
        if (double.IsPositiveInfinity(finalSize.Height) || double.IsPositiveInfinity(finalSize.Width))
            return Size.Empty;

        return finalSize;
    }

    protected override Size ArrangeOverride(Size arrangeSize)
    {
        Rect finalRect = new Rect(new Point(), arrangeSize);
        double width = arrangeSize.Width / this.Children.Count;

        foreach (var child in this.Children)
        {
            finalRect.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height);
            finalRect.Width = width;

            child.Arrange(finalRect);

            // move each child by the width increment 
            finalRect.X += width;
        }

        return arrangeSize;
    }
}

定义后,您可以像这样在ListView 上使用它

<ListView x:Name="ImageList"
            Margin="0,10,0,0"
            Style="{StaticResource HorizontalListViewStyle}"
            ItemContainerStyle="{StaticResource ImageBarListViewItemStyle}"
            SelectedIndex="{Binding SelectedIndex, ElementName=MainPivot, Mode=TwoWay}"
            Grid.Row="1">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <controls:SplitPanel />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

它会给你这个结果

无面板参考

【讨论】:

  • 我有一个类似的要求,它对我有用,虽然它导致 UI 有点卡住。
  • 奇怪,这在我的应用中从未发生过
【解决方案2】:

如果只是显示填充矩形,您可以将整个内容放在具有固定宽度和高度的Viewbox 中,并将Stretch 设置为Fill

<Viewbox Stretch="Fill" Width="220" Height="44">
    <ItemsControl x:Name="testGrid">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Rectangle Fill="{Binding}" MinWidth="44" Height="44"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Viewbox>

【讨论】:

  • 请注意,Viewbox 会缩放而不是调整大小。对于可能没问题的矩形,但对于其他控件可能不是
  • @Erno 这就是为什么我写了“如果它只是关于显示填充的矩形”。
【解决方案3】:

我不会使用Viewbox,因为它是一罐蠕虫——尽管它可能会起作用。我会使用ItemsControl 和用于其ItemsPanel 模板的自定义面板。我的工具包中的UniformGrid 几乎可以工作,但您需要以某种方式将其Columns (count) 属性绑定到列表中的元素数。如果您只需要平均划分空间,则不需要Columns 属性,但应该很容易修改。 SquareGrid 就是这样做的,但它会双向扩展。

【讨论】:

    【解决方案4】:

    您可以将 UniformGrid 与 Rows="1" 一起使用

    <UniformGrid Rows="1">
                    <Border  Margin="5,0" Background="Red" Height="20" ></Border>
                    <Border  Margin="5,0" Background="Green" Height="20" ></Border>
                    <Border   Margin="5,0" Background="Black" Height="20" ></Border>
                    <Border  Margin="5,0" Background="Gray" Height="20" ></Border>
                    <Border  Margin="5,0" Background="Orange" Height="20" ></Border>
    </UniformGrid>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-29
      • 2016-06-24
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 1970-01-01
      相关资源
      最近更新 更多