Aligning controls on both left and right side in a stack panel in WPF

87,337

Solution 1

Just do not use a StackPanel, StackPanels stack. They do, for obvious reasons, not allow alignment in the direction in which they stack. Use a Grid, with column definitions like so:

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

Solution 2

Even though this is old, should someone come across this like I did, here's a simple solution.

Make a new grid and inside that grid put two stack panels with different Horizontal Alignment.

<Grid>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
        <!--Code here-->
    </StackPanel>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
        <!--Code here-->
    </StackPanel>
</Grid>

The possible issue is that now without extra handling the two could overlap with each other.

Solution 3

As you have set the StackPanel's orientation to Horizontal, the HorizontalAlignment property won't work on child-elements. You can keep the StackPanel if you need additional controls, though I would recommend switching to a Grid (among other things) to build the layout you want.

Also, the Grid will allow you to control the actual width of each column:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50" />
        <ColumnDefinition Width="150" />
    </Grid.ColumnDefinitions>

    <RadioButton
        Grid.Column="0"
        ...
    />

    <Label
        Grid.Column="1"
        ...
    />
</Grid>

Solution 4

User @pasx is right. You should use DockPanel and dock the RadioButton to the left side, and your StackPanel with the label to the right side.

<DockPanel>

    <DockPanel 
        DockPanel.Dock="Top" 
        LastChildFill="False" >

        <RadioButton 
            DockPanel.Dock="Left" 
            Content="_Programs" 
            IsChecked="{Binding Path=ProgramBanksSelected}"
            IsEnabled="{Binding Path=ProgramsEnabled}" 
            Margin="8" />

        <StackPanel
            DockPanel.Dock="Right">

            <Label 
                Content="Master" 
                Height="28" 
                Name="MasterFileStatus" 
                VerticalContentAlignment="Center"/>

        </StackPanel>

    </DockPanel>
    ...

Solution 5

Use the Stackpanel orientation type in a nested fashion as shown in the sample. The Grid Width is set to a parent width in order to achieve full width.

<StackPanel x:Name="stackBlah" Orientation="Vertical">
    <StackPanel Orientation="Horizontal">
        <Grid Width="{Binding ActualWidth, ElementName=stackBlah}" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
            </Grid.RowDefinitions>

            <StackPanel Grid.Column="0" HorizontalAlignment="Left" >
                <Button Content="Some button" />
            </StackPanel>
            <StackPanel Grid.Column="1" HorizontalAlignment="Right">
                <ToggleSwitch Header="Some toggle" AutomationProperties.Name="ToggleNotifications"/>
            </StackPanel>
        </Grid>
    </StackPanel>
</StackPanel>
Share:
87,337
Michel Keijzers
Author by

Michel Keijzers

I'm a professional software engineer, working at Altran. I have interest in OO languages and have C++/C# knowledge (MCTS, WinForm, WPF applications). Until recently, I wrote an app for Korg music synthesizers (PCG Tools) and try to learn myself WPF at the same time. Lately, I'm into Arduino/STM32, learning the basics (and more) of electronics, and trying to build a MIDI/DMX device for MIDI keyboards and DMX512 lighting devices.

Updated on July 05, 2022

Comments

  • Michel Keijzers
    Michel Keijzers almost 2 years

    I have the following code:

    <DockPanel>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <RadioButton Content="_Programs" 
                        IsChecked="{Binding Path=ProgramBanksSelected}" IsEnabled="{Binding Path=ProgramsEnabled}" Margin="8" />
            <StackPanel>
                <Label Content="Master" Height="28" Name="MasterFileStatus" VerticalContentAlignment="Center"/>
            </StackPanel>
        </StackPanel>
        ...
    

    The radio button should be placed on the left side in the stack panel (I removed some buttons for not cluttering the example) and the label (which I put temporarily in a nested StackPanel) should be on the right side.

    I tried already lots of combinations of alignments but I cannot get the label on the right side. What should I add to accomplish this?

    • Kevin DiTraglia
      Kevin DiTraglia over 11 years
      You really can't ask too much of stack panels, as soon as you want any kind of semi-advanced structure just go for a grid
    • pasx
      pasx about 11 years
      The right answer is to use a DockPanel as in this post: stackoverflow.com/questions/2023201/…
    • jwize
      jwize almost 3 years
      And to add horizontal alignment right to the last element.
  • Kevin DiTraglia
    Kevin DiTraglia over 11 years
    Your first example will not work, they will still stack horizontally as space allows and the alignment won't do anything.
  • newfurniturey
    newfurniturey over 11 years
    @KDiTraglia Yeah, just tested - you're right; When Orientation="Horizontal", it ignores the HorizontalAlignment; removing now, thanks =]
  • Michel Keijzers
    Michel Keijzers over 11 years
    I guess that would work, however I will wait for more answers, because with StackPanels I have the benefit that when the screen is made less wide, the items will wrap up, which I loose when I use a grid.
  • H.B.
    H.B. over 11 years
    @MichelKeijzers: If you want something fancy like that you may need to implement your own panel.
  • Michel Keijzers
    Michel Keijzers over 11 years
    Thanks for the answer ... I don't know if I prefer your solution about not right aligning in that case, but that is outside of the question I asked.
  • Knasterbax
    Knasterbax over 10 years
    Works fine. Thank you!
  • Mrinmoy
    Mrinmoy about 5 years
    Thanks for tip. I took all ColumnDefinition Width="*" to equally distribute
  • Jonathan Tuzman
    Jonathan Tuzman almost 4 years
    This is a super great solution. You don't actually need the StackPanels though, if each panel only has one child.
  • Rajshekar Reddy
    Rajshekar Reddy over 2 years
    Elegant... Does the job without much of grid definitions.
  • Neha
    Neha about 2 years
    Additionally A little binding trick worked when grid is inside stackpanel . this makes grid width expand so that button appears on left and right corners of the screen. <StackPanel x:Name="sp1" Margin="10" Orientation="Horizontal"> <Grid Width="{Binding ElementName=sp1, Path=ActualWidth}" >