The XAML is a page with a list of items on it inside a Viewbox. The goal is to have a department name and them a paragraph of notes underneath that. I set the background of my itemscontrol to be Red to make it easy to see how it fills in the page.
<Grid >
<Viewbox x:Name="slideViewBox">
<ItemsControl x:Name="itemsControl" Background="Red" ItemsSource="{Binding JournalEntries}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="ParentGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" HorizontalAlignment="Left" Foreground="White" Text="{Binding Department}" FontSize="32"/>
<TextBlock x:Name="detailsTextBlock" Grid.Row="1" Foreground="White" Text="{Binding DetailedExplaination}" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="20" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>
</Grid>
What it generates:
What I ideally want:
Notice that in the first picture the details TextBlock didn't word wrap at all and a lot of usable space on the page was wasted.
I did write some code in the Size_Changed event handler that got me closer to my goal but not all the way there. I manually play with the itemscontrol width to force the text to wrap. I just need to get it to do this automatically, so that it looks like the second picture, right when the page loads.
private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
{
var child = VisualTreeHelper.GetChild(slideViewBox, 0) as ContainerVisual;
var scale = child.Transform as ScaleTransform;
double pageheight = e.NewSize.Height;
double pagewidth = e.NewSize.Width;
double textHeight;
double textWidth;
textHeight = itemsControl.ActualHeight * scale.ScaleY;
textWidth = itemsControl.ActualWidth * scale.ScaleX;
if (textWidth == pagewidth)
{
itemsControl.Width = itemsControl.ActualWidth * .9;
}
else if (textHeight == pageheight)
{
itemsControl.Width = itemsControl.ActualWidth * 1.1;
}
}
I took @user3284736's idea of applying a fixed width to the inner content, and expanded it.
First, add a property "ContainerWidth" to the view-model, and keep it updated by handling the SizeChanged
event of the view:
public MyUserControl()
{
SizeChanged += OnSizeChanged;
}
void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
ViewModel.ContainerWidth= e.NewSize.Width;
}
Now bind the width of the item template's container ("ParentGrid" in the example) to the overall container size:
<Grid x:Name="ParentGrid"
Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ContainerWidth}">
Setting a fixed size has the effect of forcing the text to wrap before the ViewBox applies its scaling.
Edit Here's the XAML I used to test:
<Grid x:Name="LayoutRoot" Background="Red">
<Viewbox Stretch="Fill" StretchDirection="Both">
<ItemsControl x:Name="itemsControl" ItemsSource="{Binding JournalEntries}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="ParentGrid"
Width="{Binding RelativeSource={RelativeSource AncestorType=ItemsControl},Path=DataContext.ContainerWidth}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" HorizontalAlignment="Left" Foreground="White" Text="{Binding Department}"
FontSize="32"/>
<TextBlock x:Name="detailsTextBlock" Grid.Row="1" Foreground="White" Text="{Binding DetailedExplanation}" HorizontalAlignment="Left" TextWrapping="Wrap" FontSize="20" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>
</Grid>