Vertical and Horizontal ScrollBars are not working - WPF - c#

I have the following code:
<DockPanel>
<Grid>
<Grid.ColumnDefinitions>
<!--This will make any control in this column of grid take 1/10 of total width-->
<ColumnDefinition Width="1*" />
<!--This will make any control in this column of grid take 4/10 of total width-->
<ColumnDefinition Width="4*" />
<!--This will make any control in this column of grid take 4/10 of total width-->
<ColumnDefinition Width="4*" />
<!--This will make any control in this column of grid take 1/10 of total width-->
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="0" Grid.Column="0">
<StackPanel>
<Image Source="/SAMPLE;component/Images/1_Left.png"/>
<Image Source="/SAMPLE;component/Images/2_Left.png"/>
<Image Source="/SAMPLE;component/Images/3_Left.png"/>
<Image Source="/SAMPLE;component/Images/4_Left.png"/>
</StackPanel>
</Border>
<ScrollViewer Grid.Row="0" Grid.Column="1">
<Canvas Name="Canvas1">
<Image Name="LeftImage"/>
<Image Name="LeftIcon"/>
</Canvas>
</ScrollViewer>
<ScrollViewer Grid.Row="0" Grid.Column="2">
<Canvas Name="Canvas2">
<Image Name="RightImage"/>
<Image Name="RightIcon"/>
</Canvas>
</ScrollViewer>
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="0" Grid.Column="3">
<StackPanel>
<Image Source="/SAMPLE;component/Images/5_Right.png"/>
<Image Source="/SAMPLE;component/Images/6_Right.png"/>
<Image Source="/SAMPLE;component/Images/7_Right.png"/>
<Image Source="/SAMPLE;component/Images/8_Right.png"/>
</StackPanel>
</Border>
</Grid>
</DockPanel>
Even though the "LeftImage" and "RightImage" are having more width and height, the scroll bars are not working. I cannot able to scroll to view the complete image. Any help ?
Thanks

Grid does not support scrolling functionality. If you want to scroll something you need ScrollViewer control. So place your grid within a ScrollViewer insted of DockPanel
<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
//Your grid
</ScrollViewer>

Related

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):
And what I want, the expected result would be:
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).
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:
If I then take that width off the grid:
This picture is the same viewbox and 700 wide grid inside a 900px wide window

WPF: Make ListBox full height of parent, but also be scrollable

I have a simple app that has three columns in the window. In the middle column, I have a ListBox component.
What I want is the ListBox to stretch the full height of the column, but also be scrollable when it has a lot of stuff in it. Right now, it's not scrollable. I can fix this by adding a Height (e.g. Height="300") property to it, but then it won't stretch with the column anymore. What do I do?
<Window x:Class="UI.MainWindow"
<!-- window stuff -->
<Border Padding="10">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MinWidth="150" MaxWidth="200" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- column 1 stuff -->
<StackPanel x:Name="LogLines" Grid.Column="1">
<StackPanel Orientation="Horizontal">
<Label>Search</Label>
<TextBox x:Name="Searchbox" Height="20" TextWrapping="Wrap" Text="TextBox" Width="120" />
<CheckBox x:Name="ErrorsOnlyCheckbox" HorizontalAlignment="Right">
Errors only
</CheckBox>
</StackPanel>
<ListBox
x:Name="LogLinesList"
ScrollViewer.CanContentScroll="True" />
</StackPanel>
<GridSplitter Grid.Column="1" Width="10" />
<!-- column 3 stuff -->
</Grid>
</StackPanel>
</Border>
</Window>
Container of your ListBox is StackPanel. StackPanel will increase regarding child controls. You should use another container, try to use Grid instead
<Grid x:Name="LogLines" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Width="Auto"/>
<RowDefinition Width="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
....
</StackPanel>
<ListBox Grid.Row="1"/>
</Grid>

Resize Images inside grid - WPF

I have to show three images in a way that center image should have double width of left or right end views. The Imagesource to Left and right end have size of 335x377 and the center imagesource have size of 403x226.
<Grid x:Name="LayoutRoot" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" ></ColumnDefinition>
<ColumnDefinition Width="*" ></ColumnDefinition>
<ColumnDefinition Width="0.5*" ></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" Background="Blue" VerticalAlignment="Center" >
<Image Name="ImageViewer1" Stretch="None" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" Background="Yellow" VerticalAlignment="Center" >
<Image Name="ImageViewer2" Stretch="None" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" Background="Red" VerticalAlignment="Center" >
<Image Name="ImageViewer3" Stretch="None" />
</StackPanel>
</Grid
Shall I need to define the size of 'ImageViewer' to achieve this ?
Unless the image widths do not more or less exactly match the column widths, it is obviously wrong to set
<Image Stretch="None" ... />
You would either set
<Image Stretch="Uniform" ... />
to make the left and right images horizontally fill their columns, or
<Image Stretch="UniformToFill" ... />
to make them also fill the row height, but cut off a bit at their sides.
You could also remove the StackPanels:
<Grid>
...
<Image x:Name="ImageViewer1" Grid.Column="0" Stretch="UniformToFill" />
<Image x:Name="ImageViewer2" Grid.Column="1" Stretch="UniformToFill" />
<Image x:Name="ImageViewer3" Grid.Column="2" Stretch="UniformToFill" />
</Grid>

WPF - Columns don't hide properly when GridSplitter is moved

I'm trying to hide a column in a Grid with a GridSplitter when a button is clicked (the button sets the visibility of all items in the third column to collapsed). If I don't move the GridSplitter it works properly and the third column disappear, but if I move the GridSplitter the content disappear but the others columns don't resize to fill the empty space.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="a" Width="*"/>
<ColumnDefinition x:Name="b" Width="3"/>
<ColumnDefinition x:Name="c" Width="Auto" MaxWidth="600"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Background="Green">
<Image Source="te/Dante.png" Height="Auto" Margin="0,128,2,71"/>
</Border>
<Button Grid.Column="0" Grid.Row="0" Width="30" Height="30" Margin="0,10,10,0" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click"></Button>
<GridSplitter Width="5" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" ResizeDirection="Columns" HorizontalAlignment="Left" Background="White" BorderBrush="Black" BorderThickness="1,0" ResizeBehavior="PreviousAndCurrent"/>
<WrapPanel x:Name="wpC" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" MinWidth="300" HorizontalAlignment="Stretch" Background="Aqua" Panel.ZIndex="-1"></WrapPanel>
</Grid>
Here is an example of my problem (gif):
How can i solve this problem? Possibly respecting MVVM pattern.
The problem is simple, you set GridSplitter ResizeBehavior="PreviousAndCurrent", but previous grid column width is * and as soon as you move splitter its width units will be changed to absolute (so it will not be able to resize when 3d column width is changed).
Simply set GridSplitter ResizeBehavior="PreviousAndNext" to solve the problem. If you do so the splitter will modify width of 3d column, but shouldn't touch first one anymore.
Btw, instead of using button and click event you can utilize ToggleButton (which IsChecked is bound to Visibility of container with content you want to hide), see this answer. Using converters with pure xaml view is better MVVM than the one with some code behind and x:Name.
Right, you have few layout problems, here is a complete solution:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Background="Green" />
<ToggleButton x:Name="toggleButton"
Width="30"
Height="30"
Margin="0,10,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Top" />
<Grid Grid.Column="1"
Visibility="{Binding IsChecked, ElementName=toggleButton, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="300"
MinWidth="300"
MaxWidth="600" />
</Grid.ColumnDefinitions>
<GridSplitter Width="5"
ResizeBehavior="CurrentAndNext" />
<WrapPanel Grid.Column="1"
Background="Aqua" />
</Grid>
</Grid>
No need for code-behind, get converter from here.
Point are: 1) put splitter inside hide-able container 2) setup grid columns to have * and fixed width (splitter doesn't work well with auto columns).
Demo:

How to Fit WPF StackPanel to Grid Cell

I have a StackPanel control in my WPF project, and it is in column 0 row 2 of a Grid. How can I autofit the StackPanel size to the size of that grid cell? Setting the StackPanel width and height to "auto" will just size it to its contents. I could explicitly set its width and height to numerical values, but I was wondering if there was a cleaner, more accurate way. Thank you.
Relevant XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="74*"/>
<RowDefinition Height="74*"/>
<RowDefinition Height="421*"/>
</Grid.RowDefinitions>
<Label Content="{StaticResource LoginWindow_Title}" Style="{StaticResource TitleH1}" Grid.ColumnSpan="2"/>
<Label Content="{StaticResource LoginWindow_Subtitle}" Style="{StaticResource TitleH2}" Grid.Row="1" Grid.ColumnSpan="2"/>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" Grid.Row="2" VerticalAlignment="Top">
<StackPanel HorizontalAlignment="Left" Grid.Row="2" VerticalAlignment="Top">
<Label Content="Log in"/>
</StackPanel>
</Border>
</Grid>
Your StackPanel is not in Grid, it`s inside Border. So for it to take all available space you can set horizontal and vertical alignment to Stretch both for it and its parent Border:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="74*"/>
<RowDefinition Height="74*"/>
<RowDefinition Height="421*"/>
</Grid.RowDefinitions>
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
BorderBrush="Black" BorderThickness="1" Grid.Row="2">
<StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Label Content="Log in"/>
</StackPanel>
</Border>
</Grid>
Even so, like others mentioned, some other panel almost definetely will be better in this case.
The answer is always the same... don't use a StackPanel for layout purposes. They are primarily used to arrange UI elements that are very unlikely to change size. Even if you resized the StackPanel to the correct size, it would not help because a StackPanel does not rearrange or resize it's content items. If you want this functionality, you'll have to use one of the other Panel controls like a Grid instead.
<Grid>
<Border>
<StackPanel VerticalAlignment="Center" ...

Categories