0

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).

Willy
  • 9,848
  • 22
  • 141
  • 284

1 Answers1

1

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

Andy
  • 11,864
  • 2
  • 17
  • 20
  • Thank you very much for you time. I am going to try it and come back here with a feedback. Only one doubt: i see that you specify a fixed width for the grid, i am wondering what happens if the screen resolution (width) is smaller or even bigger than 700px? will the grid width expand to fit the width of this parent? the code above is within a wpf usercontrol which is embedded into another control. – Willy Feb 08 '23 at 14:47
  • The viewbox fills the window in my proof of concept. That sets the size of the viewbox. The window content width is not 700px. If you do not have a fixed grid width then you'd need fixed column widths. Something has to tell layout what size everything should be. – Andy Feb 08 '23 at 15:10
  • Your solution works if you set fixed width for the grid and your screen is always of that width. But in case screen can vary its width, i mean, a width bigger than 700px then an extra space on the right is left. This could be a valid solution if you have a screen with fixed width and always the same. In my case is not working at all, my screen can have different widths. – Willy Feb 10 '23 at 16:42
  • I have solved by applying what is explained below (instead of using a single viewbox as root, enclose each control on each column within a viewbox (multiple viewboxes): https://stackoverflow.com/questions/33381736/viewbox-fill-all-column-grid-space-wpf – Willy Feb 10 '23 at 16:42
  • "But in case screen can vary its width, i mean, a width bigger than 700px then an extra space on the right is left." That's not true @Willy. The window in the pictures is 850px wide. The viewbox will fill whatever size container it is in. – Andy Feb 10 '23 at 16:59
  • I checked it and in my case when resizing the window (with bigger width) the controls at the end (the last two columns) were not being aligned to the rightmost. – Willy Feb 10 '23 at 17:07
  • Notice there are no properties set on my viewbox. In particular stretch is not set to uniform @Willy – Andy Feb 10 '23 at 19:39
  • hi Andy, do you know how can I get the same layout, i mean, last two at the rightmost and the others at the leftmost using a dockpanel? maybe changing the layout is working better and viewbox works. – Willy Feb 10 '23 at 20:44
  • You set the dock left or right and the order you put them in matters. Last child will fill by default. But you understand that layout above works, right? – Andy Feb 10 '23 at 21:30
  • I believe you, it looks like it is working because it is a pure wpf application. Using it in a wpf user control that it is inside an elementhost in order to integrate it in winforms, then it does not works. I think this is the problem, the elementhost. So i am going to mark your answer as valid for pure wpf apps but not for a mix wpf-winforms. – Willy Feb 10 '23 at 22:46