-1

Is it possible in XAML to automatically separate elements in a StackPanel no matter what the size of the window is?

In CSS with the property : space between you can send elements to both sides of the parent. This is what I want to reproduce. Is it possible ?

Two black squares on a grey background alinged left and right with a space in between.

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • if it's always two elements, then use [Grid](https://www.wpf-tutorial.com/panels/grid-rows-and-columns/) with 3 Columns, put item1 column=0, item2 column=2, Stackpanel can't span the way, you describe – dba Aug 24 '21 at 09:07
  • I didn't think of it but could maybe work. How would you do if i was a wrap panel filled with a list ? – vbstarter95 Aug 24 '21 at 09:14
  • Maybe you describe your intention, before starting guessing on several Control types :) Wrappanel, is basically a stackpanel which overflows in a new row,when the available width is exceeded.. – dba Aug 24 '21 at 09:17

1 Answers1

0

A StackPanel does not work this way , see the documentation. It does not have a notion of the available space or remaining space to divide, it just stacks elements in one direction.

Arranges child elements into a single line that can be oriented horizontally or vertically.

What you can do instead is use a DockPanel. It allows stacking controls to either side of the panel and by default the last element added to it fills the remaining space. The Border here serves as a dummy element to take the remaining space. Usually, you would put a control there that is actually used. Please be aware that this example only reproduces what you explicitly asked for, the panel allows for much more complex layouts. See remarks from the documentation.

<DockPanel>
   <Rectangle DockPanel.Dock="Left" Fill="Black" Width="100" Height="100"/>
   <Rectangle DockPanel.Dock="Right" Fill="Black" Width="100" Height="100"/>
   <Border/>
</DockPanel>

An alternative is to use a Grid with three columns, where the left and right columns use Auto as Width so the contained controls only take up as much space as they need, while the center column has its Width set to *, which will make it fit the remaining space.

<Grid>
   <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition/>
      <ColumnDefinition Width="Auto"/>
   </Grid.ColumnDefinitions>
   <Rectangle Grid.Column="0" Fill="Black" Width="100" Height="100"/>
   <Rectangle Grid.Column="2" Fill="Black" Width="100" Height="100"/>
</Grid>

The relevant portion on size attributes for Grid:

Columns and rows that are defined within a Grid can take advantage of Star sizing to distribute remaining space proportionally. When Star is selected as the height or width of a row or column, that column or row receives a weighted proportion of the remaining available space. This is in contrast to Auto, which distributes space evenly based on the size of the content that is within a column or row.


Update for your list example. You can define a data template for the items.

<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal" Margin="25,60,25,25" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplate>
      <DataTemplate>
         <Border Padding="0,25" BorderThickness="0 0 0 1" BorderBrush="#3D3C44">
            <Grid Width="378" Background="black">
               <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition/>
                  <ColumnDefinition Width="Auto"/>
               </Grid.ColumnDefinitions>
               <Label Grid.Column="0" Content="hello" Foreground="white"/>
               <Border Grid.Column="1" x:Name="PlaceholderForYourContentAndBindings" Background="Red"/>
              <theme:OnOff Grid.Column="2" Height="21" Width="38" HorizontalAlignment="Right" Grid.Column="1" Toggle="{Binding status , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MouseLeftButtonDown="OnOff_MouseLeftButtonDown" />
            </Grid>
         </Border>
      </DataTemplate>
   </ListView.ItemTemplate>   
</ListView>

ListView with a WrapPanel.

If you want two fixed columns in the ListView, use a UniformGrid instead of a WrapPanel and remove the fixed sizes. With an ItemContainerStyle the items will then scale with the window.

<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding StringItems}">
   <ListView.ItemsPanel>
      <ItemsPanelTemplate>
         <UniformGrid Columns="2" Margin="25,60,25,25" />
      </ItemsPanelTemplate>
   </ListView.ItemsPanel>
   <ListView.ItemContainerStyle>
      <Style TargetType="{x:Type ListViewItem}">
         <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
      </Style>
   </ListView.ItemContainerStyle>
   <ListView.ItemTemplate>
      <DataTemplate>
         <Border Padding="0,25" BorderThickness="0 0 0 1" BorderBrush="#3D3C44">
            <Grid  Background="black">
               <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition/>
                  <ColumnDefinition Width="Auto"/>
               </Grid.ColumnDefinitions>
               <Label Grid.Column="0" Content="hello" Foreground="white"/>
               <Border Grid.Column="1" x:Name="PlaceholderForYourContentAndBindings" Background="Red"/>
               <theme:OnOff Grid.Column="2" Height="21" Width="38" HorizontalAlignment="Right" Grid.Column="1" Toggle="{Binding status , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MouseLeftButtonDown="OnOff_MouseLeftButtonDown" />
            </Grid>
         </Border>
      </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

ListView with UniformGrid.

thatguy
  • 21,059
  • 6
  • 30
  • 40