I searched around and didn't find similar question on the forum. I have the following WPF code.
<Window x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5"
mc:Ignorable="d"
Title="MainWindow" Height="238.788" Width="406.407">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter"/>
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="Black">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter" Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox Grid.Row="3" TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter"/>
</Grid>
</Window>
When the user drags the grid splitter, only the two textbox should be resized. But what I got is like this:
How can I fix this?
Move the StackPanel and the second TextBox into a single Panel:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter"/>
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<DockPanel Grid.Row="2">
<StackPanel Orientation="Horizontal" Background="Black" DockPanel.Dock="Top">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter" Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter"/>
</DockPanel>
</Grid>
It's easy, set VerticalAlignment="Center" by the ´StackPanel´
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter"/>
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="Black" VerticalAlignment="Center">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter" Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox Grid.Row="3" TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter"/>
</Grid>
I found that the problem is not because GridSplitter can only split two before and after siblings, it's the wrong RowDefinition! In the code snippet of the question, the first and forth RowDefinition are set to Height="*", which force them to split the additional space evenly. That's why when you drag the splitter and the first and forth row always keep the same height. If I change them according to the following setting, it just works as expected.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="5" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Text="TextBox1 should be resized while moving the GridSplitter" />
<GridSplitter HorizontalAlignment="Stretch" Height="5" Grid.Row="1" />
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="Black">
<TextBlock Padding="5" Text="I want this black section have fixed height while moving the GridSplitter"
Foreground="Aqua" VerticalAlignment="Center" />
</StackPanel>
<TextBox Grid.Row="3" TextWrapping="Wrap" Text="TextBox2 should be resized while moving the GridSplitter" />
</Grid>
So no need to nest any more.
Related
I have a DockPanel, which contains some controls including a ScrollViewer.
What I WANT to happen, is for the ScrollViewer to allow the grid to be scrolled, without pushing other controls off the bottom of the form.
Instead, the ScrollViewer expands to the height of the window, rather than the top of the Button, pushing the Button off for the bottom of the form. Why is this? How do I fix it?
<Window x:Class="Class1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Class1"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="600"
WindowStartupLocation="CenterScreen">
<DockPanel LastChildFill="False">
<Menu DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Name="miQuit" Header="Quit" Click="miQuit_Click" />
</MenuItem>
</Menu>
<ToolBarTray DockPanel.Dock="Top" IsLocked="True">
<ToolBar>
<Button Name="btnQuit" ToolBar.OverflowMode="Never" Click="btnQuit_Click">
Quit
</Button>
</ToolBar>
</ToolBarTray>
<ScrollViewer VerticalScrollBarVisibility="Auto" DockPanel.Dock="Top" VerticalAlignment="Stretch">
<Grid Name="gMainGrid" ScrollViewer.CanContentScroll="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Grid.Column="0" Grid.Row="0" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="1" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="2" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="3" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="4" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="5" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="6" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="7" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="8" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="9" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="10" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="11" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="12" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="13" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="14" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="15" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="16" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="17" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="18" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="19" Width="100" Margin="10,10,10,10"/>
<TextBox Grid.Column="0" Grid.Row="20" Width="100" Margin="10,10,10,10"/>
</Grid>
</ScrollViewer>
<Button Name="btnButton1" DockPanel.Dock="Bottom" Click="btnButton1_Click" >ButtonText</Button>
</DockPanel>
I want the menu bar at the top of the screen, the button at the bottom of the screen, and the grid with the ScrollViewer in the middle. What am I doing wrong?
The problem is that the ScrollViewer doesn't know how much height it should get. ScrollViewer is a control that tries to get as much size as its children need. DockPanel also gives as much size as the ScrollViewer need and therefore your problem. You can fix height of the ScrollViewer with pixels (i.e. Height=100) To make it a fixed height. I don't know your use case so this might be useful if you are showing an image carousel for example.
In more general layout advice I might say that you'd better use a grid instead of a DockPanel:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<!-- Next one is for middle part of the page -->
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<!-- your controls here -->
</Grid>
I found that I could have a dynamic height with the DockPanel if I stuck the whole thing in a Grid. This appears to work, as I can now have a dynamic height for the ScrollViewer.
<Window x:Class="Class1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Class1"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="600"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.Row="0" LastChildFill="False">
Everything is then as normal EXCEPT that I move my button outside of the DockPanel and into the Grid's second row:
</DockPanel>
<Button Grid.Column="0" Grid.Row="1" Name="btnButton1" DockPanel.Dock="Bottom" Click="btnButton1_Click" >ButtonText</Button>
</Grid>
The rows with a Height of "Auto" will size to fit their content. The rows with a Height of asterisk (*) will size to fill the remaining space after the size of the Autos has been calculated. Thus everything sizes up correctly and nicely.
Alternatively, at this point I can do-away with the DockPanel entirely and have the Menu, ToolBarTray, ScrollViewer, and Button in their own separate grid rows, like Emad suggests in their answer (although I'm not sure what the extra row is for in their example).
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
I ultimately decided to go for that approach, so I'll mark it as the answer, but I'm putting this all here for the full explanation, for completeness (in case people do happen to want to keep their DockPanel).
I have a simple Grid with two rows, the first having a fixed height. Inside, I have an element with RowSpan="2", and on top another element which should reside only in the first row:
<Grid Background="Lime">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Grid.RowSpan="2" Height="50" Fill="Blue"/>
<TextBlock Grid.Row="0" Text="Foo" VerticalAlignment="Center" Background="Red"/>
</Grid>
However, the actualheigth of the first row simply ignores the Height setting, beeing much larger than expected.
Is this a bug in the Grid? How can I workaround this?
I think you want something like this:
<Grid Background="Lime">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Grid.RowSpan="2" Height="50" VerticalAlignment="Center" Fill="Blue"/>
<TextBlock Grid.Row="0" Text="Foo" VerticalAlignment="Center" Background="Red"/>
</Grid>
I'm not sure if having a RowSpan that covers a RowDefinition with Height="*" would work out.
i also tried this a few times, but it won't work. I think it's by design. Can't you just put the rectangle as a parent of the grid in the xaml?
It does not seem to work this way
Instead, I simply used the VerticalAlignment property to move the TextBlock to the top, and completely removed the RowDefinitions:
<Grid Background="Lime">
<Rectangle Height="50" Fill="Blue"/>
<TextBlock Grid.Row="0" Text="Foo" VerticalAlignment="Top" Background="Red" Height="20"/>
</Grid>
In this case you must use VerticalAlignment to stretch in order to fill your RowDefinition's Height.
<Grid Background="Lime">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Grid.RowSpan="2" Height="50" Fill="Blue"/>
<TextBlock Name="texto" Grid.Row="0" Text="Foo" VerticalAlignment="Stretch" Background="Red"/>
</Grid>
On this way you will see your TextBox stretched to the Row height.
I have a textbox and listview inside a grid in WPF app. What I want is, when the text overflows inside the textbox, the listview height should reduce accordingly to accommodate the textbox. Just like what happens in WhatsApp messenger when we type it in its textbox.
Here's my code:
<Grid MouseDown="ShowTextBox" Height="566" VerticalAlignment="Top" Margin="10,0,40,0" Background="White" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ListView MaxHeight="544" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled" S Grid.Row="0" Margin="20,0,0,0" x:Name="sessionNotesList" />
<TextBox Grid.Row="1" Height="Auto" MinHeight="100" MaxHeight="554" VerticalAlignment="Top" Margin="20,0,30,12" SpellCheck.IsEnabled="True" TextWrapping="Wrap" x:Name="sessionNoteContent" KeyUp="SaveNote" LostFocus="sessionNoteContent_LostFocus" />
</Grid>
Have you tried reversing the Grid.RowDefinitions so that the ListView takes all of the remaining space instead?:
<Grid MouseDown="ShowTextBox" Height="566" VerticalAlignment="Top" Margin="10,0,40,0" Background="White" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView MaxHeight="544" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled" S Grid.Row="0" Margin="20,0,0,0" x:Name="sessionNotesList" />
<TextBox Grid.Row="1" Height="Auto" MinHeight="100" MaxHeight="554" VerticalAlignment="Top" Margin="20,0,30,12" SpellCheck.IsEnabled="True" TextWrapping="Wrap" x:Name="sessionNoteContent" KeyUp="SaveNote" LostFocus="sessionNoteContent_LostFocus" />
</Grid>
I have the following XAML source to demonstrate what I am working on.
I want, when resizing the group vertically, is to have the first groupbox expand, up to its max height, then, when that is reached, expand the third groupbox.The third groupbox has a min height property, as well.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="Screen_1_Name"
x:Class="TestExpansionScreens.Screen_1"
Width="400" Height="400">
<Grid x:Name="LayoutRoot" Background="White" Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Header="Thing1" Background="LightGreen" Grid.Row="0" Grid.Column="0" MaxHeight="350">
<Button Content="Stuff1" />
</GroupBox>
<GroupBox Header="Thing2" Background="LightBlue" Grid.Row="1" Grid.Column="0">
<TextBox Text="Stuff2" Height="60" />
</GroupBox>
<GroupBox Header="Thing3" Background="Pink" Grid.Row="2" Grid.Column="0">
<TextBox Text="Stuff3" />
</GroupBox>
</Grid>
</UserControl>
Normally, when I just want a single control expanded to fill the available space, I use a DockPanel. I've built this example with all kinds of assortments of grids and dockpanels, however, I have been unable to resolve how to make it work. Any idea on how to make it happen?
Thanks
You have to set the MaxHeight on your first RowDefinition, not on the GroupBox. The row will grow up to that height and then all excess space will be occupied by the third row. You can also add a MinHeight to the third row.
<Grid x:Name="LayoutRoot" Background="White" Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="350" />
<RowDefinition Height="Auto"/>
<RowDefinition MinHeight="150" />
</Grid.RowDefinitions>
<GroupBox Header="Thing1" Background="LightGreen" Grid.Row="0" Grid.Column="0">
<Button Content="Stuff1" />
</GroupBox>
<GroupBox Header="Thing2" Background="LightBlue" Grid.Row="1" Grid.Column="0">
<TextBox Text="Stuff2" Height="60" />
</GroupBox>
<GroupBox Header="Thing3" Background="Pink" Grid.Row="2" Grid.Column="0">
<TextBox Text="Stuff3" />
</GroupBox>
</Grid>
I have a ScrollViewer, inside of which is some content. The problem is that the scroll doesn't work properly. When you scroll the content with your finger and then release, the scrollable area always snaps back to the top. It just bounces like elastic, and won't stay at the bottom where you scrolled it to.
<Grid Name="DetailPane" Margin="0,0,0,65" VerticalAlignment="Bottom" Visibility="Collapsed" Background="White" Opacity="0.85">
<StackPanel>
<Grid VerticalAlignment="Top">
<Button Margin="0" Padding="0" Click="CloseDetailPanel" HorizontalAlignment="Right" >
<Button.Content>
<Image Source="images\appbar.close.rest.small.png" Width="20" Height="20"></Image>
</Button.Content>
</Button>
</Grid>
<ScrollViewer x:Name="contentScrollViewer" VerticalAlignment="Top">
<Grid>
<StackPanel>
<TextBlock Padding="10,0,10,0" HorizontalAlignment="Left" Name="titleTextBlock" TextWrapping="Wrap" Foreground="#FF2B2929" FontWeight="Bold" />
<Image x:Name="contentThumbnail" Source="bild.jpg" Visibility="Visible" Width="400" Height="300" Margin="10" />
<TextBlock Padding="10" HorizontalAlignment="Left" Name="statusTextBlock" TextWrapping="Wrap" Foreground="#FF2B2929" />
<HyperlinkButton Padding="0,5,0,10" x:Name="WikipeadiaLink" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="More on Wikipedia" TargetName="_blank" NavigateUri="" Foreground="Blue" FontSize="18" />
</StackPanel>
</Grid>
</ScrollViewer>
</StackPanel>
</Grid>
I've actually had a similar problem before, which I managed to solve with help from Stack Overflow... and yet, here I am again, asking for help on the same topic...
thanks heaps!
UPDATE:
Based on suggestions, I removed the StackPanels and replaced them with Grids. The formatting is perfect, but I still have the same scroll problem! The content still snaps back to the beginning!
<Grid Name="DetailPane" Margin="0,0,0,65" VerticalAlignment="Bottom" Visibility="Collapsed" Background="White" Opacity="0.85">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Margin="0" Padding="0" Click="CloseDetailPanel" HorizontalAlignment="Right" >
<Button.Content>
<Image Source="images\appbar.close.rest.small.png" Width="20" Height="20"></Image>
</Button.Content>
</Button>
</Grid>
<Grid Grid.Row="1">
<ScrollViewer x:Name="contentScrollViewer" VerticalAlignment="Top">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Padding="10,0,10,0" HorizontalAlignment="Left" Name="titleTextBlock" TextWrapping="Wrap" Foreground="#FF2B2929" FontWeight="Bold" />
<Image x:Name="contentThumbnail" Grid.Row="1" Source="bild.jpg" Visibility="Visible" Width="400" Height="300" Margin="10" />
<TextBlock Grid.Row="2" Padding="10" HorizontalAlignment="Left" Name="statusTextBlock" TextWrapping="Wrap" Foreground="#FF2B2929" />
<HyperlinkButton Grid.Row="3" Padding="0,5,0,10" x:Name="WikipeadiaLink" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="More on Wikipedia" TargetName="_blank" NavigateUri="" Foreground="Blue" FontSize="18" />
</Grid>
</ScrollViewer>
</Grid>
</Grid>
Its because of the stackPanel, try replacing it with something else like Grid.
Try this, I removed a redundant grid and added stretched alignment for the scroll viewer:
<Grid Name="DetailPane" Margin="0,0,0,65" VerticalAlignment="Bottom" Visibility="Collapsed" Background="White" Opacity="0.85">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Click="CloseDetailPanel" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button.Content>
<Image Source="images\appbar.close.rest.small.png" Width="20" Height="20"></Image>
</Button.Content>
</Button>
<ScrollViewer x:Name="contentScrollViewer" VerticalAlignment="Stretch" Grid.Row="1"HorizontalAlignment="Stretch">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Padding="10,0,10,0" HorizontalAlignment="Left" Name="titleTextBlock" TextWrapping="Wrap" Foreground="#FF2B2929" FontWeight="Bold" />
<Image x:Name="contentThumbnail" Grid.Row="1" Source="bild.jpg" Visibility="Visible" Width="400" Height="300" Margin="10" />
<TextBlock Grid.Row="2" Padding="10" HorizontalAlignment="Left" Name="statusTextBlock" TextWrapping="Wrap" Foreground="#FF2B2929" />
<HyperlinkButton Grid.Row="3" Padding="0,5,0,10" x:Name="WikipeadiaLink" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="More on Wikipedia" TargetName="_blank" NavigateUri="" Foreground="Blue" FontSize="18" />
</Grid>
</ScrollViewer>
</Grid>
What solved this, in the end, was adding a static height to the ScrollViewer. I realise noone could have seen this as I omitted the part of the code that shows that this is inside a PivotItem.
According to this discussion: http://forums.create.msdn.com/forums/t/84933.aspx a ScrollViewer stops working properly when it is inside a Pivot, unless it has a static height defined.
Infuriating!