为什么我的 UserControl 大小为零?
Why does my UserControl have zero size?
我的用户控件在布局过程中似乎不遵守 HorizontalAlignment 或 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 不起作用 - 好像我没有正确参与布局过程。
有没有办法修复我的控件,使其能够按照 HorizontalAlignment 和 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 和 HorizontalAlignment 等因素。视情况而定,一些建议的大小将是合理的数字,而其他大小将是 NaN。然后我可以计算出我的图像的大小,然后将其交还。
完成后,布局引擎将调整我的 UserControl 的大小。我连接到 SizeChanged 事件,每次看到它时,我都会重新生成我的图像。生成的代码非常干净!
请注意这里的新手 - 确保为可用大小准备好 NaN 值。
我的用户控件在布局过程中似乎不遵守 HorizontalAlignment 或 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 不起作用 - 好像我没有正确参与布局过程。
有没有办法修复我的控件,使其能够按照 HorizontalAlignment 和 VerticalAlignment 的顺序拉伸以填充可用 space?
如果您觉得这里缺少一些基本内容 info/code,当然可以提问,我会补充的。您还可以在此处查看所有代码:https://github.com/gordonwatts/IndicoWalker/tree/master/IWalker/IWalker.Windows/Views
ActualHeight
不可绑定 - 它不会引发更改通知,因此您应该手动更新它。考虑一下我对这个问题的 DoubleViewModel
回答:
GridView with 2 columns, fill width
事实证明,这个特定问题的关键是参与布局引擎的过程。特别是,用户控件应该覆盖 MeasureOverride 方法。完成后,我可以删除上面 XAML 中的高度绑定。
MeasureOverride 会告诉您可用的大小,这取决于 VerticalAlignment 和 HorizontalAlignment 等因素。视情况而定,一些建议的大小将是合理的数字,而其他大小将是 NaN。然后我可以计算出我的图像的大小,然后将其交还。
完成后,布局引擎将调整我的 UserControl 的大小。我连接到 SizeChanged 事件,每次看到它时,我都会重新生成我的图像。生成的代码非常干净!
请注意这里的新手 - 确保为可用大小准备好 NaN 值。