Unable to get vertical scroll bars in an WPF TextBlock - wpf

I'm presenting text in a wpf TextBlock control (.Net 3.5). The content of the textblock varies depending on what the user selects in a list box. The text wraps, so I don't need an horizontal scroll bar. However, there is often more text than the amount the window can display, so I need a vertical scroll bar.
As I started searching I quickly found that the answer is to wrap the TextBlock in a ScrollViewer. However, It Does Not Work (TM) and I'm hoping someone can help me work out why.
This is the structure of the UI code:
<Window x:Class=..>
<StackPanel>
<ListBox HorizontalAlignment="Stretch"
VerticalAlignment="Top" Height="200"
SelectionChanged="listbox_changed" SelectionMode="Single">
</ListBox>
<Button Click="Select_clicked">Select</Button>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<TextBlock Name="textblock" TextWrapping="Wrap"/>
</ScrollViewer>
</StackPanel>
</Window>
When the user selects an item in the list box, some text associated with this item is presented in the TextBlock. I would have thought that the code as it stands should have been all that's required, but it never provides me with a scroll bar.
Searching and experimenting have given me two clues: the root of the problem might be related to me updating the content of the TextBlock dynamically, and that the TextBlock does not resize itself based on the new content. I found a posting that seemed relevant that said that by setting the Height of the TextBlock to its ActualHeight (after having changed its content), it would work. But it didn't (I can see no effect of this).
Second, if I set the height (during design time) of the ScrollViewer, then I do get a vertical scroll bar. For instance, if I set it to 300 in the xaml above, the result is almost good in that the window as first opened contains a TextBlock with a vertical scroll bar when (and only when) I need it. But if I make the window larger (resizing it with the mouse during runtime), the ScrollViewer does not exploit the new window size and instead keeps its height as per the xaml which of course won't do.
Hopefully, I've just overlooked something obvious..
Thanks!

Because your ScrollViewer is in a StackPanel it will be given as much vertical space as it needs to display it's content.
You would need to use a parent panel that restricts the vertical space, like DockPanel or Grid.
<DockPanel>
<ListBox DockPanel.Dock="Top" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Height="200"
SelectionChanged="listbox_changed" SelectionMode="Single">
</ListBox>
<Button DockPanel.Dock="Top" Click="Select_clicked">Select</Button>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<TextBlock Name="textblock" TextWrapping="Wrap"/>
</ScrollViewer>
</DockPanel>

Related

StackPanel Orientation in xaml

I got a weird problem on my xaml, in a stackPanel.
My stackPanel contains a textbox, and a button.
This should be on the same line (if possible, depending on the text width).
The problem is :
if the stackPanel have Orientation="Vertical", the button will go to the line bellow the text.
if the stackPanel have Orientation="Horizontal" , the line will not doing any break line, so all the line will go out of my grid.
<StackPanel Name="spRemplir"
Grid.Row="2"
Grid.ColumnSpan="6"
Width="560"
Margin="5,5,5,5"
Orientation="Horizontal"
VerticalAlignment="Center">
<TextBlock FontWeight="Bold"
Text={Binding Text}
TextWrapping="Wrap"/>
<Button Name="btRemplir"
Margin="5,0,0,0"
Width="150"
Content="Remplir"/>
</StackPanel>
How can I obtain a stackPanel, that will break lines if necessary, and have a text and a button on the same line?
Update with Wrapanel thanks to Eli Arbel :
<toolkit:WrapPanel Name="spRemplir"
Grid.Row="2"
Grid.ColumnSpan="6"
Margin="5,5,5,5"
Width="560"
Orientation="Horizontal">
<TextBlock FontWeight="Bold"
Text={Binding Text}
TextWrapping="Wrap"/>
<Button Name="btRemplir"
Content="Remplir"/>
</toolkit:WrapPanel>
But, the button still on the next line, while there is enough space after the text on the same line.
Itried removing the Width on the panel, but then, there is no more wrapping...
I don't understand. Even if there is stackPanel on the same Grid, they should not disturb the wrap panel right?
Thank you.
You can try a WrapPanel from the Silverlight Toolkit. Note this panel will not allow you to stretch the items to the container width.
You should also look into removing the fixed Width of the panel.
Try using a Grid instead of a StackPanel. The problem with StackPanel is that they do not report up the Visual Tree that they are out of room. This is not a bug, it's just the way they are and it's appropriate when you need it. But I avoid them except on the innermost elements. But don't have StackPanels in StackPanels as you will lose TextWrapping/Scrolling and just have elements fall of the right or bottom of the page.
Second, make sure that your outer container is Set so that the width is Constrained. For example, in your layout root, give it one Column, and set the Width for * which means = "The available space, but not more"
Once you have your outer container constrained, then your TextBlock will wrap properly.
Greg
Consider using a WrapPanel instead stack panel: http://wpftutorial.net/WrapPanel.html

ScrollViewer does not display "bar"

I have an ItemsControl wrapped in a ScrollViewer. The ScrollViewer behaves correctly but does not display correctly:
I have no Styling for ScrollViewer anywhere in my app.
The bar size looks like 0px, so the arrows end up touching.
This happens with every ScrollViewer enclosing an ItemsControl in my app.
I tested a simple ItemsControl to remove possibility of other style information effecting it:
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ItemsControl>
<TextBlock Text="test"/>
<TextBlock Text="test"/>
<TextBlock Text="test"/>
</ItemsControl>
</ScrollViewer>
and the result was the same. I also wrapped ItemsControl in a WrapPanel and set Min/Max Heights on the ScrollViewer and WrapPanel and there was no change.
Does anyone know why this is happening and how I can fix it?
Edit:
I looked at the ScrollViewer with snoop and the bizarrely Snoop's ScrollViewers also displayed incorrectly (no track bar):
Thanks

Align text vertical and horizontal center in stack panel?

I am trying to align a textblock vertically and horizontally center in a stack panel which is there in Listview but i am only able to get text vetically center but not horizontally. Plus the text is not getting wrapped. Here is the code that i have tried:
<ListBox Name="lstTiles" Margin="12,0,-12,0" Grid.Row="1" SelectionChanged="lstTiles_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Background="{StaticResource PhoneAccentBrush}" Width="145" Height="80" Margin="8,8,0,0" Orientation="Vertical" >
<TextBlock Text="{Binding Name}" Tag="{Binding ID}" Style="{StaticResource PhoneTextNormalStyle}" FontSize="15" TextWrapping="Wrap" TextAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
How can i achieve text vertically, horizontally and textwrap?
It looks like since you have the orientation of the StackPanel set to Horizontal, you're putting textblocks next to each other rather than on top of each other. Since the StackPanel elements take the size of their children, you would be able to visualize this as a horizontal, side-by-side, listing of textblocks. Since each textblock takes the size of the text that is in it, you are going to see blocks that are of varying widths, so centering horizontally is going to have no effect.
You could use margins (a pain) to accomplish equal widths. I don't recommend this.
You could also put grids of a set width in the stack panel, and put the textblocks on the grid. You may be able to set the width of the textblocks to get the right effect, but I can't test this at the moment, and I don't remember if it will cause the text to stretch or not.
For text wrapping, I assume you're talking about within the textblock, and that's easy - just set the textblock's TextWrapping property to Wrap.
Try setting the HorizontalContentAlignment and VerticalContentAlignment properties on the listboxitem. I don't have my dev computer now, so I can't experiment, but here is a post that might help you: Silverlight 3: ListBox DataTemplate HorizontalAlignment. Look at both of the first two answers, and see which one might be most helpful in your situation, substituting center, of course, in place of left, top, or stretch.

Silverlight multiple line textbox

I have looked at several code snippets where people suggest that the AcceptsReturn property of a textbox in Silverlight will enable multiple lines.
My problem however is when I add a textbox with said property and explicity set the height or allow it to fill the container, the text sits vertically in the middle of the textbox.
<Grid x:Name="LayoutRoot" >
<TextBox TextWrapping="Wrap" Text="TextBox" AcceptsReturn="True"/>
</Grid>
I need the text to anchor to the top of the textbox.
Ensure there is not an implicit style for the text box which is overriding the default expected behavior in this case. IN my case I was using the Cosmopolitan Theme from Microsoft and it had an implicit style for TextBox elements that did not produce the proper behavior.
In the resources from that theme if you look at the DefaultTextBoxStyle in the CoreStyles.xaml file, at line 448 you will find the ScrollViewer with a VerticalAlignment set to Center. Adjusting this to top solved my problem.
Try this:
<Grid x:Name="LayoutRoot">
<TextBox VerticalAlignment="Stretch" VerticalContentAlignment="Top"
TextWrapping="Wrap" Text="TextBox" AcceptsReturn="True"/>
</Grid>
The text is at the top of the box, and the the box stretches to fill the whole page.

Scrollbar in Listbox not working

I have a ListBox that displays a list of WPF controls.
My problem is that the vertical scrollbar is show but is disabled even when there are enough items that the ListBox should be scrollable.
One other possibly relevant fact is that this is contained in an Integration.ElementHost.
WPF noobie, Jim
Here is the XAML for the ListBox:
// for brevity I removed the Margin and Tooltip attributes
<Grid x:Class="Xyzzy.NoteListDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Name="stackPanel" Orientation="Vertical"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<StackPanel Orientation="Horizontal">
<CheckBox Name="AllRecent" IsChecked="False" >View All Recent</CheckBox>
<CheckBox Name="AscendingOrder" IsChecked="False">Descending Order</CheckBox>
<Button Name="btnTextCopy" Click="btnCopyText_Click">Copy All</Button>
</StackPanel>
<ListBox Name="NoteList"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
</StackPanel>
</Grid>
And the XAML for the control displayed in each ListBox item:
<UserControl x:Class="Xyzzy.NoteDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Name="Heading" FontSize="10">Note Heading</TextBlock>
<Button Name="btnCopyText" Height="20" FontSize="12"
Click="btnCopyText_Click">Copy
</Button>
</StackPanel>
<TextBlock Name="Body" FontSize="14">Note Body</TextBlock>
</StackPanel>
</Grid>
</UserControl>
I have had problems with scroll bar visibility when using a StackPanel. I think it is because the StackPanel is always as big as it needs to be to contain all of its children. Try reorganizing the layout to remove the StackPanel (use a Grid instead) and see if that helps.
You just need to introduce Height property, like this:
<ListBox Height="200"
Name="NoteList"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
Heya, I suspect what might be happening is that your ListBox is expanding enough for every item however the ListBox is actually disappearing off the bottom of the Containing Control.
Does the ListBox actually stop properly or does it just seem to disappear? Try setting a MaxHeight on the ListBox and see if that makes the scrollbar appear. You should be able to set the VerticalScrollBarVisibility to Auto to have it only appear when needed.
If the list box is inside a StackPanel, try these steps for your ListBox
Set ScrollViewer.VerticalScrollBarVisibility="Auto"
Setting the Height property of a ListBox to some height that you expect to see.
That should force the scroll bar to show up.
This is pretty late, but anyone using ListBox probably shouldn't have it in a StackPanel. Once I switched the parent control of my Listbox from StackPanel to DockPanel with LastChildFill=True (Where the listbox was the last control), my scrollbar worked perfectly.
Hope this helps someone who's problem was not solved by the above answer.
Another solution to this problem that works well is to put a ScrollViewer around the StackPanel.
Another solution with a modification to Dave's is to use the ScrollViewer only. You only be able to scroll by placing your mouse on the ScrollView's ScrollBar. I use it this way because I don't like how ListBox jumps from item to item and sometimes missing items from the Top. Little bit hard on the eyes too. I like ScrollViewer's smooth scrolling.
I just ran into the same issue, and here's a little code demo on code project that visually shows it.
(If you want to save yourself the time of writing the code to see the differences yourself :) )
http://www.codeproject.com/Tips/659066/ListBox-and-Panels-in-WPF

Resources