Issue with ScrollViewer in WPF - c#

I am working on a WPF application and using a scrollViewer to view the content that is offlimit the screen area. Working fine, no issues.
But if my window contains a Listbox or Grid or anything like that and that control has many records then instead of adding a scrollbar to itself, it just increase the height of the control and window itself because scrollviewer believes it needs to extend.
I don't want to hardcode the listbox's height, because that make it same in different resolutions, i want to make it increase its height but not always as scrollviewer make it do so.
Thanks

You can't include a variable height/width object inside a ScrollViewer without setting the height/width of the viewer.
The scroll viewer effectively has infinite height so the grid expands to fill the "available" space - hence the effect you are seeing. As #JoeWhite says in his comments, the ScrollViewer is a container that can be as tall as it needs to be to hold all of its content. Anchoring wouldn't help - in effect, your ListBox already is anchored, it's just anchored to something that says "oh, I'll be whatever size you need me to be".
You'll need to either restrict the height, move the ListBox outside the ScrollViewer or use something other than a ScrollViewer.
Again quoting #Joe "These are the hazards of putting a scrolling area inside another scrolling area - it's poor usability and it's hard to define the behaviour."

You can wrap ScrollViewer into Grid, and bind scrollviewer's Width and Height properties to grid's ActualWidth and ActualHeight. So the scrollviewer will have fixed size equal to the size of the grid which will change when window resize.
Example:
<Grid x:Name="LayoutRoot" Background="White">
<Grid Background="#FFF1F1F1" Height="49" VerticalAlignment="Top">
<Button Content="Обзор" Margin="0,13,175.25,0" VerticalAlignment="Top" FontSize="14.667" HorizontalAlignment="Right" Width="95.147">
</Button>
<Label Content="{Binding DocPath, Converter={StaticResource FileNameConverter}, FallbackValue=Выберите файл, TargetNullValue=Выберите файл}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="342.603" Margin="10,10,0,0" Height="33"/>
<Button Content="Загрузить данные" HorizontalAlignment="Right" Margin="0,13,10,0" VerticalAlignment="Top" Width="151.147" FontSize="14.667">
</Button>
</Grid>
<Grid x:Name="scrollBorder" Margin="10,54,10,10">
<ScrollViewer x:Name="LogScroller" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
HorizontalAlignment="Left" VerticalAlignment="Top"
Height="{Binding ActualHeight, ElementName=scrollBorder}" Width="{Binding ActualWidth, ElementName=scrollBorder}" >
<ItemsControl ItemsSource="{Binding Log}" />
</ScrollViewer>
</Grid>
</Grid>

Related

WPF ScrollViewer is not working

I want to add scroll view to my program and I tried ScrollView control but that don't take effect. It's my first time dealing with scrolls please help me :).
My xaml Code:
<DockPanel Grid.Row="1" Background="#FF695887">
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="795">
<Canvas Name="zemelapis" Height="Auto" Width="Auto">
<Image Name="pav_kelias" />
<Image Name="car1" />
</Canvas>
</ScrollViewer>
</DockPanel>
Because these 2 images is not fitting here I need a scroll for them. Maybe I should use ScrollBar?
My program example: https://gyazo.com/a4ba7e4d5004632e2229a87e686c4c09
, as you can see bottom image is not fitting in range of window.
You have specified Auto as Height and Width. This implies that the Canvas will fill the height available to it.
From the documentation:
Auto sizing behavior implies that the element will fill the height
available to it.
In this case the available height is the height of the ScrollViewer.
If you want the Canvas to be bigger, and hence the ScrollViewer to scroll, you should set a height on Canvas that is bigger than the height of ScrollViewer.
So, for example:
<DockPanel Grid.Row="1" Background="#FF695887">
<ScrollViewer VerticalScrollBarVisibility="Auto" Height="795">
<Canvas Name="zemelapis" Height="1000" Width="Auto">
<Image Name="pav_kelias" />
<Image Name="car1" />
</Canvas>
</ScrollViewer>
</DockPanel>
If you want your ScrollViewer to work easily, use a Grid instead of a Canvas:
<DockPanel Background="#FF695887">
<ScrollViewer >
<Grid Name="zemelapis">
<Image Name="pav_kelias" Source="acteurs.png"/>
<Image Name="car1" Source="public.jpg"/>
</Grid>
</ScrollViewer>
</DockPanel>
As explain by Domysee, Canvas gives you total control of the layout. Grid however will automatically adjust its size depending on the content.
See http://www.wpf-tutorial.com/panels/introduction-to-wpf-panels/

ScrollBar Disabled

I was trying to implement a ScrollViewer like so;
<Height="auto" Width="auto"
MaxHeight="500" MaxWidth="400"
ResizeMode="NoResize" WindowStyle="None">
<Grid>
<StackPanel>
<ScrollViewer Name="scrlBr">
<StackPanel Orientation="Vertical">
<TextBlock Name ="txtBlock" Margin="10" Height="auto"
Width="auto" TextWrapping="Wrap"></TextBlock>
<Button Name="btnOk" Click="btnOk_Click" Width="80"
HorizontalAlignment="Center">Close!</Button>
</StackPanel>
</ScrollViewer>
<Label HorizontalAlignment="Center" FontSize="3"
Name="lblScrollDown">\/</Label>
</StackPanel>
</Grid>
</Window>
The problem I'm having is that the scroll bar appears disabled, while the text obviously goes down off the window and I can't see the btnOk. Surely if the window has a fixed height and the TextBlock and Button, which are contained in the Scrollviewer, are bigger than the window then the ScrollBar should be enabled, no?
UPDATE
I worked out that the problem lies in having the ScrollViewer within a StackPanel. Might try it with a Grid instead... Update to come.
SOLUTION
I was right about the Stackpanel being the problem and went with Heinzi's suggestion of using the DockPanel and all's workin' fine. :) Thanks!
The problem is your StackPanel. It always takes all the vertical space it needs, so the container of the ScrollPanel is much larger than the window itself, and the ScrollViewer sees no need to scroll.
Solution: Replace the StackPanel with a DockPanel. Move the <Label> declaration to the top and dock it to the bottom of the DockPanel. The last child in a DockPanel (which is the ScrollViewer in this case) always fills the remaining space:
<Grid>
<DockPanel>
<Label DockPanel.Dock="Bottom" ... Name="lblScrollDown">\/</Label>
<ScrollViewer Name="scrlBr">
...
</ScrollViewer>
</DockPanel>
</Grid>
Try setting the CanContentScroll property on True from the ScrollViewer and set a fixed height of the StackPanel, as a StackPanel is designed to grow indefinitely in one direction. Or better, use a different panel to stack your items in.
Maybe you need write something like this
<ScrollViewer Name="scrlBr" VerticalScrollBarVisibility="auto" HorizontalScrollBarVisibility="auto">
...
</ScrollViewer>

Resize WPF application

Have tried searching google but I'm struggling to find an answer to this.
I have a basic WPF application with a few controls on. When I maximise the application the controls on the screen stay the same size and I get a lot of wasted space.
Is there a way to get the controls to grow and shrink dynamically with the size of the main window?
Kind Regards
Ash
Don't set a fixed Height and Width properties for your controls.
Instead set, horizontal and vertical alignment to stretch. And make sure your controls are contained inside an appropriate layout panel.
For example-
Fixed size grid:
<Grid Background="Red" Width="50" Height="50"/>
Dynamically expending grid:
<Grid Background="Red" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
what you need is not resize, it's called scaling (or zooming) ;-)
Read this article; the task is very trivial with WPF.
(used to be much more complicated in Windows Forms...).
UI Scaling (UI Zooming) with WPF
basically all you need to add to the XAML is this:
<ScaleTransform
CenterX="0" CenterY="0"
ScaleX="{Binding ElementName=uiScaleSlider,Path=Value}"
ScaleY="{Binding ElementName=uiScaleSlider,Path=Value}"
/>
after that you can use mouse wheel or a slider or any other way (like in your case detect form maximized), to modify the Value of the ScaleTransform.
Where there's a will, there's a way. You will have to do some work yourself however, WPF can't automagically decide for you exactly how you want the resizing to be done.
Some relevant sources:
Layout containers
Data Binding
You can use content decorator that can stretch and scale a single child to fill the available space - Viewbox .
http://www.wpftutorials.com/2011/04/wpf-viewbox.html
this is no problem. The behavior of your controls depends on the container you use and the Horizontal and Vertical Alignment. For Example, if you use a Grid, a TextBox and a Button with Horizontal and Vertical Alignment: Stretch and width and height auto, the Textfield and Button will grow and shrink dynamically.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<TextBox Margin="8,8,8,104.96" TextWrapping="Wrap" Text="TextBox" Height="auto" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Button Content="Button" Margin="8,0,8,8" VerticalAlignment="Bottom" Height="92.96" Width="auto" HorizontalAlignment="Stretch"/>
</Grid>
Use a resizable control like Grid and put all the controls in Rows/Columns. Also set HorizontalAlignment to stretch for each control.

Image height inside Stack Panel

I'm designing a imaging gallery with Scroll Viewer and Stack Panel in WPF like the following:
<ScrollViewer x:Name="ShopsScroll" Grid.Row="1" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<StackPanel x:Name="stackPanel" Margin="0" Orientation="Horizontal" Height="Auto">
<Image Source="Images/1F/L1_angesb.jpg"/>
<Image Source="Images/1F/L1_chanel.jpg"/>
<Image Source="Images/1F/L1_dior.jpg"/>
<Image Source="Images/1F/L1_gucci.jpg"/>
<Image Source="Images/1F/L1_LV.jpg"/>
<Image Source="Images/1F/L1_nike.jpg"/>
</StackPanel>
Since the image is large in size, I would like to resize them to fit the height of the StackPanel. However, when I set the value of height in StackPanel as "Auto", it just used the height of the image, not its parent ScrollViewer. If I set a fix value to StackPanel, the problem seems being fixed, but I need to use my application in different size of screen in full screen. Thus, it should adapt different size but not hard code a fix value.
How I I do it?
You could use an element binding to bind the height of your images to the height of the StackPanel element. Sorry I can't test this code right now, but try something like
<Image Source="Images/1F/L1_nike.jpg" Height="{Binding ElementName=ShopsScroll, Path=Height}" />
See MSDN documentation on the Binding.ElementName property.
This property is useful when you want to bind to the property of another element in your application. For example, if you want to use a Slider to control the height of another control in your application, or if you want to bind the Content of your control to the SelectedValue property of your ListBox control.
Try to set HorizontalAlignment = "Stretch" and VerticalAlignment = "Stretch" for stackpanel
In my opinion better to have ItemsControl with images in it in your case
<ItemsControl HorizontalContentAlignment="Stretch">
<Image Source="Images/1F/L1_angesb.jpg"/>
<Image Source="Images/1F/L1_chanel.jpg"/>
<Image Source="Images/1F/L1_dior.jpg"/>
<Image Source="Images/1F/L1_gucci.jpg"/>
<Image Source="Images/1F/L1_LV.jpg"/>
<Image Source="Images/1F/L1_nike.jpg"/>
</ItemsControl>
Hope this helps

Scroll bar, if Items exceed inside itemControl

I have ItemControl
It displays one panel for each record inside ObservableCollection.
My Problem is….
When size of ObservableCollection increase window can’t accommodate more panels so it displays only first six panels.
So criteria, One panel for each record inside ObservableCollection,couldn't be accomplish.
So, I need to have scroll bar so I can access each panel.
How does it can be implement?
See one screen shot below and Code of It Here
Thanks......
You need to host your panel within a ScrollViewer. This allows it to grow beyond the space available to it, whilst the ScrollViewer adds a Scrollbar.
You can do this by modiyfing the ItemsControl template:
<ItemsControl>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
Put any controls you want to have scrollbars into the ScrollViewer. Example taken from MSDN:
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock TextWrapping="Wrap" Margin="0,0,0,20">Scrolling is enabled when it is necessary.
Resize the window, making it larger and smaller.</TextBlock>
<Rectangle Fill="Red" Width="500" Height="500"></Rectangle>
</StackPanel>
</ScrollViewer>

Categories