WPF: Scrollviewer not limiting content to size of window - wpf

I have a treeview with a scrollviewer. When the treeview becomes to full with treenodes i want the scrollbar to show up. But no matter how big the treeview gets it never shows up. The treeview grows outside of window without limiting itself to staying inside window.
The structure is currently:
MainWindow contains a Frame that displays a page, the page contains a usercontrol, the usercontrol contains a treeview.
The usercontrol is set to "stretch", but instead of stretching to fit it's parent (limiting the space and thus making scrollbar appear), it stretches to fit all it's children (and thus stretching outside of screen).
How would i go on about making the "auto" sizing limiting itself to it's parent, instead of making it showing all children?
How i would like it to look/work like
How it actually looks/works like
Code, kinda irrelevant, i just wanna know how i should apply scrollview:
MainWindow:
<Frame Source="View/Pages/StartPage.xaml" x:Name="MainFrame" NavigationUIVisibility="Hidden"/>
</DockPanel>
MainPage:
<Grid>
<Frame Source="ParamFrameV.xaml" x:Name="pageFrame" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
ParamFrameV (the usercontrol):
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top" MaxHeight="I WANNA LIMIT HEIGHT SO THAT IT WONT GO OFF SCREEN" Width="283">
<TreeView ItemsSource="{Binding Nodes}" ItemContainerStyle="{StaticResource TreeViewItemExpandedStyle}">
//irrelevant code for this question
</TreeView>
</ScrollViewer>

that works just fine for me:
<Grid>
<ScrollViewer Height="{Binding ElementName=ParentGridName, Path=ActualHeight"}" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" VerticalAlignment="Top" Width="283">
<TreeView Width="50" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<TreeViewItem Header="hi"></TreeViewItem>
<TreeViewItem Header="hi2"></TreeViewItem>
<TreeViewItem Header="hi3"></TreeViewItem>
<TreeViewItem Header="hi4"></TreeViewItem>
<TreeViewItem Header="hi5"></TreeViewItem>
<TreeViewItem Header="hi6"></TreeViewItem>
<TreeViewItem Header="hi7"></TreeViewItem>
<TreeViewItem Header="hi8"></TreeViewItem>
</TreeView>
</ScrollViewer>
</Grid>
Note:
scroling on the treeview itself will not scroll as it will capture your scroll event but i bet there is a way around this

Related

How do you make a vertically scrolling scrollviewer inside a tabControl?

I want to make it so that my TabControl is vertically scrollable, but I can't seem to do it. The following sample acts as though there was no scrollviewer at all. I even tried putting the TabControl inside the scrollviewer, or putting it all in a grid and constraining the height of the grid, but nothing works.
<DataTemplate x:Key="tabControlTemplate">
<TabControl ItemsSource="{Binding guiItems}" DisplayMemberPath="Title" Height="Auto" Template="{StaticResource mainTabControlTemplateEx}">
<TabControl.ContentTemplate>
<DataTemplate>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
<StackPanel Margin="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl ItemsSource="{Binding guiItems }" ItemTemplateSelector="{DynamicResource templateSelector}"/>
</StackPanel>
</ScrollViewer>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</DataTemplate>
The actual problem is not clear from the question.
You are not getting to see scrollviewer and the content inside is clipped? PLease confirm if that is the case.
If the problem is you are getting to see entire content taking up all the available space, and you would like to control that using scroll viewer, then you would need to set 'MaxHeight' property on Scroll Viewer. This would limit the height of your DataTemplate and would make verticall scroll bar visible if the inner content goes beyond the MaxHeight.
Hope that helps.

Correct way to set ScrollViewer (for vertical scrolling) on a WPF Frame?

does anyone know the difference between defining a vertical scrollbar on a frame like this:
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
<Frame Name="Frame1"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
or like this:
<ScrollViewer Grid.Row="2">
<Frame Name="Frame1"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
This frame is nested in a WebBrowser control and setting it the first way correctly displays the vertical scrollbar and is only visible when it needs to scroll (auto). When I set it the second way the vertical scrollbar works but is always visible even when it does not need to scroll (visible).
I am going to use the 1st option because it meets my needs, but I don't want to be surprised down the road if I am setting it incorrectly.
Thanks!
When you use ScrollViewer.VerticalScrollBarVisibility or ScrollViewer.HorizontalScrollBarVisibility attached property it has no effect with Frame.
<ScrollViewer Margin="225.667,-4,0,296.939" HorizontalAlignment="Left" Width="221.667">
<Frame Content="Frame" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Hidden" Source="UserControl2.xaml" Background="#FFDE5454"/>
</ScrollViewer>
In example above I used both ScrollViewer.VerticalScrollBarVisibility and ScrollViewer.HorizontalScrollBarVisibility attached properties. outcome of that code is the exact opposite of what you would expect. There is no HorizontalScrollBar visible... and you can still see VerticalScrollBar.
So that's why this is what you should use
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
<Frame Name="Frame1" />
</ScrollViewer>
When you try this for example with ListBox then result will be different.
This is the result of following code:
<ScrollViewer Margin="225.667,0,0,12.761" Height="280.178" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="221.667">
<ListBox ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible" Background="Orange" ItemsSource="{Binding Collection}" DisplayMemberPath="Property1" />
</ScrollViewer>
That's because those attached properties now affect ScrollViewer within ListBox and not parent ScrollViewer as you may expect.
So from this little experiment I assume that ScrollViewer.VerticalScrollBarVisibility attached property is meant for cases where you want to be able to affect ScrollViewer which exists within Control's template and not parent ScrollViewer. So I think it does not work for example as DockPanel.Dock which takes effect on parent DockPanel.

Silverlight Scrollviewer Mousewheel scrolls only when scrolled on datagrid. Page doesn't scroll when scrolled outside the datagrid

Page scrolls without any issue when the mouse is over data grid. If the mouse outside datagrid page doesn't scroll.
<navigation:Page>
<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ScrollViewer x:Name="scrollMainQueue" VerticalScrollBarVisibility="Auto" >
<StackPanel>
<StackPanel>
</StackPanel>
.......
<StackPanel>
<data:DataGrid AutoGenerateColumns="False" Name="grdWorkingDocs" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="50" Margin="5,0,5,5" CanUserResizeColumns="False" CanUserReorderColumns="False" LoadingRow="grdWorkingDocs_LoadingRow" AlternatingRowBackground="White" RowBackground="White" HorizontalGridLinesBrush="White" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled" />
</StackPanel>
</StackPanel>
......
</StackPanel>
</ScrollViewer>
</Grid>
scrollMainQueue.SetIsMouseWheelScrollingEnabled(true);
After some research Got the answer.
Basically we need to set the background color to the scrollviewer. It worked after that.
<ScrollViewer x:Name="scrollMainQueue" VerticalScrollBarVisibility="Auto" Background="White">
Answer is as mentione above. Applied background color to scrollviewer made is scrollable.
Background="Transparent" also works, if you can't use any color because of your design requirements.
I was using the Content Control to hold the inner view wrapped up with scroll viewer, the scroll viewer was only working on mouse wheel when the pointer is on any field and not on the empty area.
After seeing the above posts, I set the background color and it started working fine, though the solution looks unrelated [don't know how exactly related to the problem].

Constraining a ListView's width to parent to force child text to wrap

I'm trying to get a window similar to a chat window, where a list of text items is drawn. The window should be resizable and each text item should wrap if it does not fit on one line.
What I have so far:
MessageItem - A user control, multiline TextBlock in a Border
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Border BorderBrush="Silver" BorderThickness="1" Height="Auto" HorizontalAlignment="Left" Margin="0,10,0,10" Name="messageContainer" VerticalAlignment="Top" Width="Auto">
<TextBlock Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="messageContent" VerticalAlignment="Stretch" Width="Auto" Text="This is some longer text. Wow that wasn't as long as I thought." TextWrapping="Wrap" Padding="10" />
</Border>
</Grid>
MessageBox - A user control with a ListView that holds MessageItems
<Grid Name="messageGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<!--<StackPanel Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="messagePanel" VerticalAlignment="Stretch" Width="Auto">
</StackPanel> -->
<ListView HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<local:MessageItem></local:MessageItem>
</ListView>
</ScrollViewer>
</Grid>
The Problem:
If I use the commented out StackPanel for holding MessageItems, It will shrink the MessageItem (and cause the text to wrap) correctly. If I use the ListView, it does not shrink.
I've more or less figured out why from research, but I haven't been able to figure out how to get around it. As far as I can tell I need to override MeasureOverride and/or ArrangeOverride, but I'm far too new to WPF to know WTF I'm doing. (rimshot)
I'm not sure why you're putting the ListView inside a ScrollViewer since the ListView has its own ScrollView internally.
In order to get your MessageItems to wrap you need to turn off any horizontal scrollbars, otherwise the container (ListView or ScrollViewer) will give the MessageItem as much space as it requires and show a scrollbar.
Try
<ScrollViewer ... ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
and
<ListView ... ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
although I'm not sure you even need the ScrollViewer.
You would probably be better off using a ListBox and an ItemTemplate instead of the ListView and user control

ListView with nested Expander not collapsing

This question is the same as this other unanswered question.
When the Expander is expanded the outer ListView grows to make space for the expanders contents, but when the Expander is then collapsed the view does not force the ListView to resize.
Reduced code, with notes after:
<!--<StackPanel>-->
<ItemsControl>
<!-- ParameterGroupView -->
<Border BorderBrush="Brown" BorderThickness="1" CornerRadius="4" Padding="4">
<ListView HorizontalContentAlignment="Stretch">
<Expander Header="Expander A" IsExpanded="False">
<ListView HorizontalContentAlignment="Stretch">
<!-- TextView -->
<TextBlock >Content A</TextBlock>
<TextBlock >Content B</TextBlock>
</ListView>
</Expander>
</ListView>
</Border>
</ItemsControl>
<!--</StackPanel>-->
I have the ParameterGroupView in a ItemsControl or StackPanel because there is actually many ParameterGroupView entries. Swapping to a StackPanel does not change the behaviour.
Removing the Boarder does not affect the behaviour, but having it helps show the behaviour with only a single ParameterGroupView.
There can be many Expander sections in the outer ListView, and the Expander can have many entities inside the inner ListView.
The outer ListView and Expander is to replace a TreeView, that was used to have a list of collapsible nodes, but the TreeView's internal use of grids, means the TextView items were squashed horizonatlly, the same as if you remove ether HorizontalContentAlignment="Stretch" attributes.
So if there is another way to wrap/wire all this up, I'll be also happy.
This is a problem because our TextView blocks are large and there are many Expanders.
Edit: TextView is used as the code is data-bound, and thus dynamically put together. So any replacement for ListView would need some form of ItemsSource
Found the solution, and it details where in the question already.
ItemControl accepts an ItemsSource and auto resizes. So replacing the two ListViews with ItemControls gets the nested collapsing.
But there is no scrolling, so wrapping the outer ItemControl with a ScrollViewer, reproduces the complete desired effect.
<ScrollViewer
VerticalScrollBarVisibility="Auto">
<ItemsControl>
<!-- ParameterGroupView -->
<Border
BorderBrush="Brown"
BorderThickness="1"
CornerRadius="4"
Padding="4"
Height="Auto">
<ItemsControl
HorizontalContentAlignment="Stretch">
<Expander
Header="Expander A"
IsExpanded="False">
<ItemsControl
HorizontalContentAlignment="Stretch">
<!-- TextView -->
<TextBlock>Content A</TextBlock>
<TextBlock>Content B</TextBlock>
</ItemsControl>
</Expander>
</ItemsControl>
</Border>
</ItemsControl>
</ScrollViewer>
I was testing with double Expanders in the Border and double Border sections.
The most obvious thing to do here is to put the expanders in a container other than a listview:
<Border BorderBrush="Brown" BorderThickness="1" CornerRadius="4" Padding="4">
<StackPanel>
<Expander Header="Expander A" IsExpanded="False">
<ListView HorizontalContentAlignment="Stretch" MinWidth="100">
<ListBox Name="listb"></ListBox>
<!-- TextView -->
<TextBlock >Content A</TextBlock>
<TextBlock>Content B</TextBlock>
</ListView>
</Expander>
</StackPanel>
</Border>
The container resizes around content just fine.
If you absolutely must have it in a ListView (which is possible) then I don't know of a way to get a ListView to resize easily once it's grown (beyond setting explicit sizes of the whole thing, which is clumsy and not useful). If thats the case then it's possible that you'll have to use a controllable listbox to display all the open expanders, or display the content in a different way (like in a popup, maybe?) if you want to be able to see it all at a glance.

Resources