Reputation: 1107
I am setting up printing functionality in my app. To do this, I have two pages: PrintPage
and OverflowPage
. Both inherit from my custom abstract Page
, PrintablePage
. Here are the XAML layouts for them:
PrintPage.xaml
<RelativePanel>
<RelativePanel x:Name="Header"
BorderBrush="Gray"
BorderThickness="0 0 0 1"
Margin="48 48 48 12"
Padding="0 0 0 6"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignTopWithPanel="True">
<TextBlock x:Name="RouteTextBlock"
Style="{ThemeResource TitleTextBlockStyle}"
Text="{x:Bind Route, Mode=OneWay}" />
<TextBlock x:Name="StaffTextBlock"
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
Margin="0 6 0 0"
RelativePanel.Below="RouteTextBlock"
Text="{x:Bind Staff, Mode=OneWay}"
TextWrapping="Wrap" />
<TextBlock x:Name="Legend"
FontSize="14"
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
Margin="0 12 0 24"
RelativePanel.Below="StaffTextBlock">
<Run FontFamily="/Assets/Fonts/Kimble.ttf#Kimble-UWP"
FontSize="16"
Text="" /> = Parent must be present for pickup
</TextBlock>
<Grid x:Name="DataHeader"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="Legend">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="48" />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="NameHeader"
FontWeight="SemiBold"
Grid.Column="2"
Grid.Row="2"
Text="Name" />
<TextBlock x:Name="AddressHeader"
FontWeight="SemiBold"
Grid.Column="3"
Grid.Row="2"
Text="Address" />
<TextBlock x:Name="AgeHeader"
FontWeight="SemiBold"
Grid.Column="4"
Grid.Row="2"
HorizontalTextAlignment="Right"
Text="Age" />
</Grid>
</RelativePanel>
<RichTextBlock x:Name="MainContentTextBlock"
HorizontalAlignment="Stretch"
RelativePanel.Above="InstructionsTextBlock"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="Header" />
<TextBlock x:Name="InstructionsTextBlock"
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
Margin="0 0 0 24"
RelativePanel.AlignHorizontalCenterWithPanel="True"
RelativePanel.AlignBottomWithPanel="True"
Text="Please fill out this form and return it at the end of the night" />
</RelativePanel>
OverflowPage.xaml
<RelativePanel Margin="0 0 0 12">
<Grid x:Name="Header"
BorderBrush="Gray"
BorderThickness="0 0 0 1"
Margin="48 48 48 12"
Padding="0 0 0 6"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignTopWithPanel="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="48" />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="NameHeader"
FontWeight="SemiBold"
Grid.Column="2"
Grid.Row="2"
Text="Name" />
<TextBlock x:Name="AddressHeader"
FontWeight="SemiBold"
Grid.Column="3"
Grid.Row="2"
Text="Address" />
<TextBlock x:Name="AgeHeader"
FontWeight="SemiBold"
Grid.Column="4"
Grid.Row="2"
HorizontalTextAlignment="Right"
Text="Age" />
</Grid>
<RichTextBlockOverflow x:Name="OverflowBlock"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="Header" />
</RelativePanel>
In the constructor for PrintPage
I render a list of items:
var pageWidthBinding = new Binding
{
FallbackValue = 0,
TargetNullValue = 0,
Source = this,
Path = new PropertyPath("PageWidth"),
Mode = BindingMode.OneWay
};
foreach (var child in Children)
{
var uiContainer = new InlineUIContainer();
var contentPresenter = new ContentPresenter
{
Content = child,
ContentTemplate = ChildItemTemplate
};
contentPresenter.SetBinding(WidthProperty, pageWidthBinding);
uiContainer.Child = contentPresenter;
var paragraph = new Paragraph { LineHeight = 18, Margin = new Thickness(0) };
paragraph.Inlines.Add(uiContainer);
MainContentTextBlock.Blocks.Add(paragraph);
}
PageWidth
is a DependencyProperty
which I set in the page's SizeChanged
event handler.
The ChildItemTemplate
:
<DataTemplate x:Name="ChildItemTemplate"
x:DataType="models:Child">
<Grid Height="18"
Margin="48 12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="48" />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<FontIcon x:Name="ParentPresentIcon"
x:Load="{x:Bind ParentMustBePresent}"
FontFamily="/Assets/Fonts/Kimble.ttf#Kimble-UWP"
FontSize="16"
Foreground="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
Glyph=""
Grid.Column="0"
HorizontalAlignment="Center" />
<Border x:Name="HereCheckBox"
BorderBrush="{ThemeResource ApplicationSecondaryForegroundThemeBrush}"
BorderThickness="1"
CornerRadius="2"
Grid.Column="1"
Height="18"
HorizontalAlignment="Center"
Width="18" />
<TextBlock Grid.Column="2"
Text="{x:Bind FullName}" />
<TextBlock Grid.Column="3"
Text="{x:Bind Address}" />
<TextBlock Grid.Column="4"
HorizontalTextAlignment="Right"
Text="{x:Bind Age}" />
</Grid>
</DataTemplate>
I have two helper methods on PrintPage
and OverflowPage
which the print service calls:
public override PrintablePage GetOverflowContent() =>
new OverflowPage(MainContentTextBlock);
and
public override bool HasOverflow() =>
MainContentTextBlock.HasOverflowContent;
The constructor for OverflowPage
then sets the parameter's (a RichTextBlock
) OverflowContentTarget
property to OverflowPage
's OverflowBlock
.
This all works fine. However, there's one bug I seem to have hit. The system doesn't appear to properly calculate the HasOverflowContent
property. As you can see in this image, there is clearly overflow content (it's being clipped), yet HasOverflowContent
is always false.
(Note that there is content being rendered correctly on the rest of the page, but I've erased it for privacy reasons.)
This is happening on OverflowPage
, but I think it's safe to assume the same problem would also be present on PrintPage
.
Am I missing something that's affecting my layout, or is this a bug in the system?
Apologies for the wall of text, but with what appears to be a layout issue I think I'd better post any code that could possibly affect it.
Upvotes: 1
Views: 167
Reputation: 12019
HasOverflowContent
isn't necessarily available synchronously; you need to wait for it to become available. But simply listening to the LayoutUpdated
event or awaiting
for the next UI tick aren't enough - you need to do both. This answer from a related question has code to do it.
Upvotes: 1