为什么我的 UserControl 大小为零?

Why does my UserControl have zero size?

我的用户控件在布局过程中似乎不遵守 Horizo​​ntalAlignment 或 VerticalAlignment。

我有一个 Windows 商店 XAML 用户控件定义如下:

<UserControl
    x:Class="IWalker.Views.PDFPageUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:IWalker.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="200"
    d:DesignWidth="250">

    <Image x:Name="ThumbImage"/>

</UserControl>

它位于 ItemsControl 水平列表中,如下所示(为简洁起见,我将 Page XAML 声明放在顶部 - 但它来自 Windows Store 空白模板):

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ScrollViewer VerticalScrollMode="Disabled" HorizontalScrollMode="Auto" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
        <ItemsControl x:Name="SlideStrip">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:PDFPageUserControl Margin="0 0 5 0" Height="{Binding Path=ActualHeight, ElementName=SlideStrip, Mode=OneWay}" ViewModel="{Binding}" RespectRenderingDimension="Vertical" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Grid>

如您所见,PDFPageUserControl 将其 Height 绑定到它将所在的 ItemsControl 的 ActualHeight。发生这种情况时,一切正常。如果我删除该绑定,那么我的用户控件大小为 0,0。

这是棘手的部分。 PDFPageUserControl 没有隐式大小。我需要设置它的高度、宽度或两者(如您在上面的代码片段中看到的那样)。然后它将使用 PDF 渲染代码生成正确大小的图像并显示它(所有这些都有效)。

我的理论是 Windows Store XAML 的自动布局,默认情况下,不会尝试扩展内容直到它们适合。它让大多数控件确定自己的大小并将其报告给布局引擎。然后布局引擎围绕它们进行布局,构建。我的报告它最初是 0,0,等待被告知它的高度,以便它可以通知系统它的宽度,反之亦然。由于 ItemsControl 的 StackPannel 从不强制项目拉伸以适合其内部,因此不会发生这种情况。

但是,很明显,某些控件可以扩展以填充所有可用的控件 space - 就像这里的 Grid 或 ScrollViewer。我原以为水平和垂直对齐的 "Stretch" 模式会在布局引擎中为您完成此操作。但这似乎对我的 UserControl 不起作用 - 好像我没有正确参与布局过程。

有没有办法修复我的控件,使其能够按照 Horizo​​ntalAlignment 和 VerticalAlignment 的顺序拉伸以填充可用 space?

如果您觉得这里缺少一些基本内容 info/code,当然可以提问,我会补充的。您还可以在此处查看所有代码:https://github.com/gordonwatts/IndicoWalker/tree/master/IWalker/IWalker.Windows/Views

WinRT/XAML 中的

ActualHeight 不可绑定 - 它不会引发更改通知,因此您应该手动更新它。考虑一下我对这个问题的 DoubleViewModel 回答:

GridView with 2 columns, fill width

事实证明,这个特定问题的关键是参与布局引擎的过程。特别是,用户控件应该覆盖 MeasureOverride 方法。完成后,我可以删除上面 XAML 中的高度绑定。

MeasureOverride 会告诉您可用的大小,这取决于 VerticalAlignment 和 Horizo​​ntalAlignment 等因素。视情况而定,一些建议的大小将是合理的数字,而其他大小将是 NaN。然后我可以计算出我的图像的大小,然后将其交还。

完成后,布局引擎将调整我的 UserControl 的大小。我连接到 SizeChanged 事件,每次看到它时,我都会重新生成我的图像。生成的代码非常干净!

请注意这里的新手 - 确保为可用大小准备好 NaN 值。