Specify the max number of columns for a WrapPanel in WPF

前端 未结 4 510
广开言路
广开言路 2021-02-07 03:13

I have a WrapPanel, And I want to specify the Max number of its columns. So, for example, when my Collection \"ObjectCollection\" (binded to this WrapPanel) contains only 4 elem

相关标签:
4条回答
  • 2021-02-07 03:53

    I'm pretty sure you can't do it with a WrapPanel, but you can use the UniformGrid instead.

    That one has properties to specify the number of rows and columns you want.

    If you set the Columns property to 4, it will keep 4 items in each row, and then wrap to the next one.

    <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>
    
    0 讨论(0)
  • 2021-02-07 03:54

    You can control the number of columns by setting the width of the wrap panel. I bind the width of the wrap panel to the ActualWidth of a container like Border. That way, the number of columns is dynamic and is based on the width of the window.

    <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>
    
    0 讨论(0)
  • 2021-02-07 03:56

    Sometimes the UniformGrid is not enough:

    • when items are of very different sizes, or
    • when you want items vertically and don't want to use other workarounds

    In this stackoverflow post can be found a WrapPanel with what you are searching for.

    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>
    

    Result:

    0 讨论(0)
  • 2021-02-07 03:57

    Basically you're going to need to create a custom Panel for yourself... now don't get despondent... it's not that difficult. To start with, please take a look at the posts that I have provided links for that explain how to create a custom Panel:

    How to create a Custom Layout Panel in WPF

    Creating Custom Panels In WPF

    Ok, so now that you know a bit more about creating custom Panels, we can continue... here's what you're going to need:

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

    This property would be used where you declare your Panel in Resources:

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

    Note that you will need to declare it inside an ItemsPanelTemplate object because that is what the ItemsPanel property expects:

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

    Now back to the Panel... here is a helper method that I call from the MeasureOverride and ArrangeOverride methods:

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

    Unfortunately for you, I cannot provide you with a complete example because my custom Panels are all tied into a base AnimatedPanel class with lots of additional functionality. However, you only need to create the MeasureOverride and ArrangeOverride methods to complete this Panel. If you just think logically about it, it's really not that difficult.

    0 讨论(0)
提交回复
热议问题