Prevent ScrollViewer from changing its Content size - c#

I want the ScrollViewer to do only one thing - allow me to scroll. I don't want it to allow its Content to grow. Yet it does. How to prevent that?
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="a.png"/>
<Grid Grid.Row="1" Height="400"/>
</Grid>
</ScrollViewer>
If I comment out the ScrollViewer - the Image is small. If I leave the ScrollViewer - the Image grows. How to prevent that?

You would avoid stretching the Image by setting its Stretch property to None.
<Image Grid.Row="0" Stretch="None" .../>
The Grid and hence the Image element use the full width of the scrollable area. Since the default Stretch value is Uniform, the Image subsequently adjusts its height to keep its aspect ratio.
An equivalent, but simpler layout would be
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel>
<Image Stretch="None" Source="a.png"/>
<Grid Height="400"/>
</StackPanel>
</ScrollViewer>

Related

StackPanel height exceed parent Grid height

I have situation like this:
<UserControl>
<Grid x:Name="fullGrid" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="innerGrid" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="leftSide" VerticalAlignment="Stretch">
<ScrollViewer VerticalAlignment="Stretch">
<ItemsControl/ VerticalAlignment="Stretch">
</ScrollViewer>
</StackPanel>
</Grid>
</Grid>
</UserControl>
Problem is that leftSide stackPanel height is higher than it's parent: innerGrid height.
I was debugging it in Snoop and it seems that StackPanel just ignore it's VerticalAlignment property.
I would like to avoid setting Heigh={Binding ElementName=xxx, Path=ActualHeight} because I have some additional Margins inside, and it break the view.
How can I handle that?
ScrollViewer fills its parent. StackPanel wants to size to its children, and so tells them they have as much space as they want (and then "shrinks to fit").
So, StackPanel tells ScrollViewer it can have all the space in the world, which it happily takes. There is no way to stop this besides doing a binding as you describe or setting an absolute height.
So the simple solution is: remove the StackPanel. Then the ScrollViewer will take up the space the Grid assigns it.

Portrait Images in Grid are cutoff - WP8

I am trying to bind Landscape and Portrait Images to the grid control. The Landscape images are loaded correctly, but I'm facing problems when it comes to load portrait images. Their bottom part is cut off(overflowed) so the grid row can't load the image with it's full Height. I tried setting the Row property with Height="Auto" or Height="*" but that didn't work.
Here is my XAML:
<ItemsControl ItemsSource="{Binding ItemsPrasanja}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock
Name="txtPrasanje"
Grid.Row="0"
Text="{Binding Tekst}"
TextWrapping="Wrap"/>
<Image Name="imgPrasanje"
Grid.Row="1"
Source="{Binding Slika}"
Margin="0,5,0,0"
/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
How can i solve this without setting manually Width or Height to the Grid or the Image control ?
P.S. The ItemsControl is part from another Grid control. It populates (Grid.Row="0") which I set to Height=" * "
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
You should look into the Stretch property of the Image object
A value of Fill will cause your image to stretch to completely fill the output area. When the output area and the image have different aspect ratios, the image is distorted by this stretching. To make an Image preserve the aspect ratio of the image, set this property to Uniform (default) or UniformToFill.

MaxHeight on RowDefinition with Height=Auto ignored

The property MaxHeight seems to be ignored on RowDefinitions with Height="Auto":
Consider the following XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MaxHeight="100"/>
</Grid.RowDefinitions>
<ListBox>
<ListBox.Items>
<ListBoxItem>a</ListBoxItem>
<ListBoxItem>b</ListBoxItem>
<ListBoxItem>c</ListBoxItem>
<ListBoxItem>d</ListBoxItem>
<ListBoxItem>e</ListBoxItem>
<ListBoxItem>f</ListBoxItem>
<ListBoxItem>g</ListBoxItem>
<ListBoxItem>h</ListBoxItem>
<ListBoxItem>i</ListBoxItem>
<ListBoxItem>j</ListBoxItem>
</ListBox.Items>
</ListBox>
</Grid>
The Grid will be bigger than 100 dip.
How can I constrain a RowDefinition in its Height?
Must be something else. Tried it in a clean Window and the listbox stops at 100 pixels.
Maybe check your styling.
Set the height on the grid to auto and leave maxheight on the rowdefinition.
For Example:
<Grid Height="Auto" Width="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="20" MinHeight="20" MaxHeight="20"/>

Keep slider in usercontrol from scaling in WPF

I have a user control which contains a media element to play a video, a slider used as a trackbar for the video and a text block that display the title of the video. These 3 controls are placed in a grid which in turn is placed inside a border.
I want the user to be able to translate, rotate and scale this control. The problem is that when the control scales it's content scales also and i want the slider control not to scale. Is it possible to somehow keep the slider control from scaling?
I should also mention that the manipulation of the control is handled by setting the control ismanipulationenabled to true and using the manipulation delta event.
EDIT:
This is how the xaml for the control looks like:
<Grid Name="movieGrid" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="moviePlayerBorder" Background="Black" BorderBrush="Blue" BorderThickness="2,2,2,2" CornerRadius="5,5,5,5" Grid.RowSpan="2">
<Grid Name="contentGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<WinControls:MediaElement x:Name="movieDisplay" ScrubbingEnabled="True" IsEnabled="True" Grid.RowSpan="2"
LoadedBehavior="Manual" UnloadedBehavior="Manual"
MediaOpened="movieDisplay_MediaOpened">
</WinControls:MediaElement>
<Image x:Name="btnPlay" Grid.Row="1" Height="60" Width="60" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="120,44,112,43" Grid.RowSpan="2">
</Image>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch" Margin="6,2,6,0" Grid.Row="0">
<TextBlock Text="test" Margin="0,0,0,0" Name="txtBlockTitlu" HorizontalAlignment="Stretch"
FontSize="14" VerticalAlignment="Top" Foreground="White" TextWrapping="Wrap" Visibility="Collapsed"/>
</DockPanel>
</Grid>
</Border>
<Slider x:Name="seekBar" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="299"
Thumb.DragStarted="seekBar_DragStarted" Thumb.DragCompleted="seekBar_DragCompleted" Thumb.DragDelta="seekBar_DragDelta" MaxHeight="33"
Minimum="0" Maximum="286" Height="33" Margin="0,0,0,0" Grid.Row="1"/>
</Grid>
if you want to build a fully scaleable user control you should define the layout only with the size values of a row column / row row eg. auto, x* or fixed values (if realy needed).
do not use fixed size values on elements.

ListBox is contained in a ScrollViewer

I would like the ScrollViewer of the page to be displayed when all the information cannot be shown on the screen (i.e. resize the window)
However, the ListBox here doesn't get a scroll and it gets sketch till the bottom of the page unless i set it to have a MaxSize. Is there a way to give priority to the ListBox to display its ScrollViewer before the one I have made?
what i have right now
http://i.imgur.com/bEJcz.png
what i would like to achieve, but i used a MaxHeight for the ListBox here.
Here's some my markup:
<ScrollViewer HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" Name="scrollViewer1" VerticalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left"></ComboBox>
<ListBox HorizontalAlignment="Left" Name="listBox" Width="120" Grid.Row="1" <!--MaxHeight="500"--> />
</Grid>
</ScrollViewer>
I know this question is old, but I had exactly the same problem and came up with a bit of a hack as a fix but its better than having the question unsolved.
Much of what I've read states that using things like StackPanel is bad in this case because the panel grows to fit the elements it holds. Normally this works fine because you can stick the StackPanel into a Grid and set the MinHeight and MaxHeight of the column/row and lock the controls in place. As soon as the ScrollView is added this kind of goes to hell. The answer above describes the problem well, but lacks a solution.
I tried many different types of Panels instead of a StackPanel but they all yield the same result. I decided that since my ListBox sits inside of a Grid, I needed to bind the MaxHeight of that grid location to some other value in the control to keep the ListBox from growing. The problem with this is that there is no element that you can bind straight to and get the exact height your looking for.
Enter the hack:
My height was just a tiny bit too big creating a weird always offscreen ListBox (in fact 36 pixels too large, which was the height of the label above the ListBox). So I implemented the IValueConverter:
class HeightToAdjustedHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var height = (double) value - 33d;
return height < 360d ? 360d : height;
//360 being the minimum height allowed for the listbox
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
All I did after that was include it as a converter for the binding on MaxHeight (Note you need to name your usercontrol and bind to its x:Name):
<Grid Grid.Column="0"
Grid.Row="1"
VerticalAlignment="Top"
ClipToBounds="True"
MaxHeight="{Binding ElementName=AdHocUserControl, Path=ActualHeight, Converter={StaticResource HeightToAdjustedHeightConverter}}">
The only other alternative I can think of is to extend one of the panels and try to play with its growth behavior. I admit this is a hack, but it will work.
Try this
<ScrollViewer HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" Name="scrollViewer1" VerticalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left" ></ComboBox>
<ListBox HorizontalAlignment="Left" Name="listBox" Width="120" VerticalAllignment = "Top" Grid.Row="1"/>
</Grid>
</ScrollViewer>
Or you can also try this
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left" ></ComboBox>
<ListBox HorizontalAlignment="Left" Name="listBox" VerticalAlignment= "Top" Width="120" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</Grid>
You have a logical inconsistency in your definitions.
The requirement as you put it: "I would like the scrollviewer of the page to be displayed when all the information cannot be shown on the screen [without using MaxHeight]" - a question arises: "How do you determine that 'all the information cannot be shown on the screen'?" or "At what point the ListBox should stop growing and show the scroll bar?".
From a WPF\Silverlight layout management logic, it does exactly what you want - when the sum of height of list box plus the height of the combo box is greater than the ViewportHeight of the scroll viewer - you get a scroll bar. That is possible only when you allow the ListBox to grow to it's desired size without scroll bars.
Dont set the MaxHeight on the ListBox, just use the star '*' notation in your RowDefinitions to get the relative sizing between your 2 controls correct.
Another solution:
<ScrollViewer HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" Name="scrollViewer1" VerticalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Width="120" HorizontalAlignment="Left"></ComboBox>
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Disabled" >
<ListBox HorizontalAlignment="Left" Name="listBox" Width="120" Grid.Row="1" MaxHeight="{Binding ActualHeight, ElementName=scrollViewer}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</ScrollViewer>
</Grid>

Categories