Укажите максимальное количество столбцов для WrapPanel в WPF

У меня есть WrapPanel, и я хочу указать максимальное количество его столбцов. Так, например, когда моя Коллекция «ObjectCollection» (привязанная к этому WrapPanel) содержит только 4 элемента, WrapPanel будет иметь только одну строку. Но когда «ObjectCollection» будет иметь 5 элементов, wrapPanel создаст еще одну строку для размещения пятого. (My Max_Columns_Number в этом случае 4).


person NTinkicht    schedule 05.09.2013    source источник
comment
вам действительно не нужно писать свою настраиваемую панель, для этого просто используйте сетку вместо wrappanel в качестве панели элементов в списке. хотя вам нужно будет указать каждому элементу списка, к какой строке или столбцу сетки он принадлежит   -  person ninja hedgehog    schedule 05.09.2013


Ответы (4)


Я почти уверен, что вы не сможете сделать это с помощью 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>
person Peter Hansen    schedule 05.09.2013

По сути, вам нужно будет создать собственный Panel для себя ... не отчаивайтесь ... это не это сложно. Для начала ознакомьтесь с сообщениями, на которые я предоставил ссылки, в которых объясняется, как создать собственный Panel:

Как создать панель настраиваемого макета в WPF

Создание настраиваемых панелей в WPF

Итак, теперь, когда вы знаете немного больше о создании пользовательских Panels, мы можем продолжить ... вот что вам понадобится:

private int columnCount;
private double leftColumnEdge, rightColumnEdge, columnWidth;

public int ColumnCount
{
    get { return columnCount; }
    set
    {
        if (value < 1) value = 1;
        columnCount = value;
    }
}

Это свойство будет использоваться там, где вы объявляете свой Panel в Resources:

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

Обратите внимание, что вам нужно будет объявить его внутри объекта ItemsPanelTemplate, потому что этого ожидает свойство ItemsPanel:

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

Теперь вернемся к _11 _... вот вспомогательный метод, который я вызываю из методов MeasureOverride и ArrangeOverride:

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

К сожалению для вас, я не могу предоставить вам полный пример, потому что все мои пользовательские Panel связаны с базовым AnimatedPanel классом с множеством дополнительных функций. Однако вам нужно создать только методы MeasureOverride и ArrangeOverride, чтобы завершить это Panel. Если подумать логически, это действительно не так уж и сложно.

person Sheridan    schedule 05.09.2013
comment
Ну это про уровень. Это больше похоже на вас или на меня :) Он вроде не разбирается в верстке. Ему бы лучше было использовать Grid или UniformGrid. - person ninja hedgehog; 05.09.2013
comment
Я полностью согласен с этим, но надеюсь, некоторые пользователи со временем сочтут эту страницу полезной. - person Sheridan; 05.09.2013
comment
Конечно, там происходит много всего. измерение процесса детализации, расчет, организация. Но решать, начинать с нуля или нет, остается за пользователем. - person ninja hedgehog; 05.09.2013

Вы можете контролировать количество столбцов, задав ширину панели переноса. Я привязываю ширину панели обтекания к ActualWidth контейнера, такого как Border. Таким образом, количество столбцов будет динамическим и зависит от ширины окна.

<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>
person BDH    schedule 24.08.2015

Иногда UniformGrid недостаточно:

  • когда предметы очень разных размеров, или
  • если вам нужны элементы вертикально и не нужно использовать другие обходные пути

В этом сообщении stackoverflow можно найти 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>

Результат:

введите здесь описание изображения

person frakon    schedule 31.01.2017