【问题标题】:Specify the max number of columns for a WrapPanel in WPF指定 WPF 中 WrapPanel 的最大列数
【发布时间】:2013-09-05 11:45:14
【问题描述】:

我有一个 WrapPanel,我想指定它的最大列数。因此,例如,当我的集合“ObjectCollection”(绑定到此 WrapPanel)仅包含 4 个元素时,WrapPanel 将只有一行。但是,当“ObjectCollection”有 5 个元素时,wrapPanel 将创建另一行来放置第五个元素。 (在这种情况下我的 Max_Columns_Number 是 4)。

【问题讨论】:

  • 您实际上不需要为此编写自定义面板,只需使用网格而不是 wrappanel 作为列表框中的项目面板。尽管您必须告诉每个列表框项它属于哪个网格行或列

标签: c# wpf data-binding wrappanel


【解决方案1】:

我很确定您不能使用 WrapPanel 来做到这一点,但您可以改用 UniformGrid

那个有属性来指定你想要的行数和列数。

如果您将Columns 属性设置为4,它将在每行中保留4 个项目,然后换行到下一个。

<UniformGrid Columns="4">
    <!-- In first row -->
    <Button Content="test"></Button>
    <Button Content="test"></Button>
    <Button Content="test"></Button>
    <Button Content="test"></Button>

    <!-- In second row -->
    <Button Content="test"></Button>
</UniformGrid>

【讨论】:

    【解决方案2】:

    基本上,您需要为自己创建一个自定义Panel...现在不要沮丧...这并不那么困难。首先,请查看我提供链接的帖子,这些帖子解释了如何创建自定义 Panel

    How to create a Custom Layout Panel in WPF

    Creating Custom Panels In WPF

    好的,既然您对创建自定义 Panels 有了更多了解,我们可以继续...这是您需要的:

    private int columnCount;
    private double leftColumnEdge, rightColumnEdge, columnWidth;
    
    public int ColumnCount
    {
        get { return columnCount; }
        set
        {
            if (value < 1) value = 1;
            columnCount = value;
        }
    }
    

    此属性将用于您在Resources 中声明您的Panel

    <ItemsPanelTemplate x:Key="AnimatedPanel">
        <Controls:AnimatedColumnWrapPanel ColumnCount="3" ... />
    </ItemsPanelTemplate>
    

    请注意,您需要将其声明为 ItemsPanelTemplate 对象中,因为这是ItemsPanel 属性所期望的:

     <ListBox ItemsPanel="{StaticResource AnimatedPanel}" ... />
    

    现在回到 Panel... 这是我从 MeasureOverrideArrangeOverride 方法调用的辅助方法:

    private void UpdateColumns(int currentColumn, Size finalSize)
    {
        leftColumnEdge = (finalSize.Width / ColumnCount) * currentColumn;
        rightColumnEdge = (finalSize.Width / ColumnCount) * (currentColumn + 1);
        columnWidth = rightColumnEdge - leftColumnEdge;
    }
    

    很遗憾,我无法为您提供完整的示例,因为我的自定义 Panels 都绑定到具有许多附加功能的基本 AnimatedPanel 类中。但是,您只需要创建MeasureOverrideArrangeOverride 方法即可完成此Panel。如果你只是从逻辑上思考,真的没那么难。

    【讨论】:

    • 这是专业级别的。这更像是你或我:) 他似乎不懂布局。使用 Grid 或 UniformGrid 会更好。
    • 我完全接受这一点,但希望随着时间的推移,一些用户会发现此页面有用。
    • 确实发生了很多事情。测量下钻过程,计算,安排。但由用户决定是否从头开始。
    【解决方案3】:

    您可以通过设置环绕面板的宽度来控制列数。我将包装面板的宽度绑定到像 Border 这样的容器的 ActualWidth 上。这样一来,列数是动态的,并且基于窗口的宽度。

    <Border Name="DataBorder" Grid.Row="0" Grid.Column="1"
            BorderBrush="Navy" BorderThickness="1,2,2,2"
            Padding="4">
            <Grid>
                 <Grid.RowDefinitions>
                      <RowDefinition Height="Auto"></RowDefinition>
                      <RowDefinition Height="*"></RowDefinition>
                  </Grid.RowDefinitions>
    
                  <StackPanel>
                      <TextBlock Text="{Binding NewPictureCountDisplay}"></TextBlock>
                  </StackPanel>
    
                  <ListBox Name="NewFilesListBox" Grid.Row="1"
                           ItemsSource="{Binding CreatedFiles}">
                      <ListBox.ItemsPanel>
                          <ItemsPanelTemplate>
                              <WrapPanel Orientation="Horizontal" Width="{Binding ElementName=DataBorder, Path=ActualWidth}"></WrapPanel>
                          </ItemsPanelTemplate>
                      </ListBox.ItemsPanel>
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="*"></RowDefinition>
                                            <RowDefinition Height="Auto"></RowDefinition>
                                        </Grid.RowDefinitions>
    
                                        <Image Grid.Row="0" Source="{Binding FullPath}" Width="128" Height="128" Stretch="UniformToFill"></Image>
    
                                        <StackPanel Grid.Row="1" Orientation="Vertical">
                                            <Button Content="Import" Margin="2"></Button>
                                            <Button Content="Delete" Margin="2"></Button>
                                            <TextBlock HorizontalAlignment="Stretch" Text="{Binding FullPath}" Margin="2"></TextBlock>
                                            <TextBlock HorizontalAlignment="Stretch" Text="{Binding ChangeType}" Margin="2"></TextBlock>
                                        </StackPanel>
    
                                    </Grid>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
    

    【讨论】:

      【解决方案4】:

      有时 UniformGrid 是不够的:

      • 当项目的大小非常不同时,或
      • 当你想要垂直的项目并且不想使用other workarounds

      this stackoverflow post 中可以找到一个WrapPanel,其中包含您要搜索的内容。

      Xaml:

      <loc:WrapPanelWithRowsOrColumnsCount
          xmlns:loc="clr-namespace:..."
          Orientation="Vertical"
          RowsOrColumnsCount="2">
          <TextBox Text="Andrew" Margin="2" Height="30" />
          <TextBox Text="Betty" Margin="2" Height="40" />
          <TextBox Text="Celine" Margin="2" Height="20" />
          <TextBox Text="Dick" Margin="2" Height="20" />
          <TextBox Text="Enron" Margin="2" Height="30" />
          <TextBox Text="Felix" Margin="2" Height="20" />
          <TextBox Text="Hanibal" Margin="2" Height="30" />
      </loc:WrapPanelWithRowsOrColumnsCount>
      

      结果:

      【讨论】:

        猜你喜欢
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-07
        • 1970-01-01
        • 1970-01-01
        • 2017-02-06
        • 1970-01-01
        相关资源
        最近更新 更多