Search code examples
c#wpfxaml.net-4.5viewbox

Viewbox interfering grid columns horizontal alignment


I am using a Viewbox with Stretch set to Uniform in order to not distort the content when user switches between screen resolutions and scale in the OS.

Within the Viewbox I have a grid. The grid has only 1 row and some columns.

<Viewbox StretchDirection="Both" 
         Stretch="Uniform"
         HorizontalAlignment="Left"
         VerticalAlignment="Stretch">

        <Grid Focusable="True"
              Height="Auto">
            <Grid.ColumnDefinitions>
                <!-- Animated image -->
                <ColumnDefinition Width="Auto" />
                <!-- Stack panel with icon and text -->
                <ColumnDefinition Width="Auto" />
                <!-- A vertical separator -->
                <ColumnDefinition Width="Auto" />
                <!-- A button -->
                <ColumnDefinition Width="Auto" />
                <!-- Empty dummy column to help distribute space correctly between columns so it will cause next columns to be horizontally right aligned. -->
                <ColumnDefinition Width="*" />
                <!-- Help button -->
                <ColumnDefinition Width="Auto" />
                <!-- Three dots button -->
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <StackPanel Grid.Column="0"
                        Orientation="Horizontal"
                        Visibility="{Binding Path=IsAnimatedImgVisible, Converter={StaticResource BoolToVisibility}}">
                <v:UserControlAnimatedImg x:Name="UcSpinner" VerticalAlignment="Center" HorizontalAlignment="Left"/>
                <Label SnapsToDevicePixels="True"
                   RenderOptions.BitmapScalingMode="HighQuality"
                   VerticalAlignment="Center" HorizontalAlignment="Left"
                   Content="{Binding Path=StatusText}"/>
            </StackPanel>


           <StackPanel Grid.Column="1"
                       Orientation="Horizontal">

                <Image
                   Margin="10,5"
                   Height="24"
                   Width="24"
                   MaxHeight="24"
                   MaxWidth="24"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"
                   Stretch="None" 
                   SnapsToDevicePixels="True"
                   RenderOptions.BitmapScalingMode="HighQuality"
                   Source="{Binding Path=Icon}"/>

                <Label 
                   VerticalAlignment="Center"
                   HorizontalAlignment="Left"
                   Content="{Binding Path=StatusTxt}"
                   SnapsToDevicePixels="True"
                   RenderOptions.BitmapScalingMode="HighQuality">
                </Label>
            </StackPanel>

            <Separator Grid.Column="2"
                   Margin="10,5,5,5"
                   Height="26"
                   Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}">

           <Button Grid.Column="3"
                Height="Auto"
                Width="150"
                Command="{Binding ButtonOnClick}">
                <StackPanel Orientation="Horizontal">
                    <Image 
                       Height="24"
                       Width="25"
                       MaxHeight="24"
                       MaxWidth="25"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       Stretch="None" 
                       SnapsToDevicePixels="True"
                       RenderOptions.BitmapScalingMode="HighQuality"
                       Source="{Binding ImageIcon}"/>

                    <TextBlock
                           Margin="10,2,5,2"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Left"
                           Text="{x:Static p:Resources.BtnText}"
                           SnapsToDevicePixels="True"
                           RenderOptions.BitmapScalingMode="HighQuality">
                    </TextBlock>
                </StackPanel>
            </Button>

            <!-- Empty dummy space to help distribute space correctly between columns and
                 make next columns to be horizontally right aligned. This column will be blank   
                 space.-->
            <ContentControl Grid.Column="4"/>

            <Button 
                Grid.Column="5"
                Height="25"
                Width="25"
                MaxHeight="25"
                MaxWidth="25"
                Margin="8,0,5,0"
                Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                Command="{Binding BtnHlpClick}">
                <Image HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Stretch="Uniform"
                   SnapsToDevicePixels="True"
                   RenderOptions.BitmapScalingMode="HighQuality"
                   Source="{Binding ImageHelpIcon}"/>
            </Button>

            <StackPanel Grid.Column="6"
                    x:Name="PlaceHolder"
                    VerticalAlignment="Center"
                    Margin="2,0,12,0"
                    Width="27"
                    Height="Auto">
                <Image
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Stretch="Uniform"
                   Height="20"
                   Width="20"
                   SnapsToDevicePixels="True"
                   RenderOptions.BitmapScalingMode="HighQuality"
                   Source="{Binding ImgThreeDotsIcon}">
                    <Image.ContextMenu>
                        <ContextMenu Placement="Bottom" Background="#FFFFFF">
                            <MenuItem Header="{x:Static p:Resources.mnutext}" Command="{Binding MenuOnClick}"></MenuItem>
                        </ContextMenu>
                    </Image.ContextMenu>
                </Image>
            </StackPanel>
</Viewbox>

The first column is shown or not depending on a condition. Here I will show you only the use case with the first column not visible.

Above code produces below result (first column not visible):

enter image description here

And what I want, the expected result would be:

enter image description here

I want the last two columns (5 and 6) horizontally aligned to the rightmost and an extra blank space between columns 3 and 5. Note that column 4 is used as a dummy column to make this extra blank space area and its width is set to "*" in columndefinitions.

How can I get the expected result? If I remove the Viewbox then I get the expected result but I want to get the same result with the Viewbox added. I need the viewbox as root, i don't want to remove it, because using it I make content to be independent of the screen resolution and scaling (Viewbox does it automatically).


Solution

  • I think you need an explicit width for your grid.

    Or at least once I set that, things work better.

    You've not shown us a minimal reproduction of your issue so I made one myself.

    I used some rectangles for this.

    Note there is fixed size for the grid so measure arrange knows how big everything should be in order for * to work.

    </Window.Resources>
        <Viewbox>
            <Grid Width="700">
                <Grid.ColumnDefinitions>
                    <!-- Animated image -->
                    <ColumnDefinition Width="Auto" />
                    <!-- Stack panel with icon and text -->
                    <ColumnDefinition Width="Auto" />
                    <!-- A vertical separator -->
                    <ColumnDefinition Width="Auto" />
                    <!-- A button -->
                    <ColumnDefinition Width="Auto" />
                    <!-- Empty dummy column to help distribute space correctly between columns so it will cause next columns to be horizontally right aligned. -->
                    <ColumnDefinition Width="*" />
                    <!-- Help button -->
                    <ColumnDefinition Width="Auto" />
                    <!-- Three dots button -->
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Rectangle Width="100" Height="50" Grid.Column="0"
                           Fill="Red" Margin="4"/>
                <Rectangle Width="100" Height="50" Grid.Column="1"
                           Fill="Red" Margin="4"/>
                <Rectangle Width="100" Height="50" Grid.Column="7"
                           Fill="Red" Margin="4"/>
            </Grid>
        </Viewbox>
    

    If I choke down the size it still retains the proportions:

    enter image description here

    If I then take that width off the grid:

    enter image description here

    This picture is the same viewbox and 700 wide grid inside a 900px wide window

    enter image description here