我编写了一个 WPF 用户控件,其中一部分涉及向画布动态添加元素,从而影响所述画布的高度。画布嵌套在网格中。当我动态添加我的元素时,画布的高度会发生变化,但画布最终会延伸到整个控件的边缘之外,而不是导致控件调整大小并使其自身更高。如何强制控件正确调整大小?我觉得我需要调用或覆盖 Measure 或 Arrange,但我对这两种方法都没有运气 - 可能是因为我使用不正确的参数调用它们,或者可能是因为它们不是要调用的正确方法。
4 回答
您的问题是 Canvas 面板不会调整大小以适应其内容。
您提到了测量和排列。你熟悉 WPF 的两遍布局系统吗?阅读这篇文章了解更多信息:WPF 的布局系统。
本文还介绍了不同面板对布局的作用。每种类型的面板都是不同的。
在 WPF 中,元素首先有机会确定它们的大小。小组可以根据孩子的大小来确定他们的大小,或者他们可以要求固定大小而不管孩子的大小。帆布是后者的一个例子。
元素接下来会被告知它们的大小,并要求他们安排自己和他们的孩子。
Grid 面板类型不仅允许行和列,而且非常擅长根据内容自动调整大小。
StackPanel 类型在它所面向的维度中根本不会自动调整大小,但会在另一个维度中自动调整大小。
画布可以自动调整大小以填充空间,但它永远不允许它的孩子自动调整大小。它在指定的坐标处绘制它的孩子,而不关心它们有多大。
我建议尝试只有一行/列的网格。
或者,您可以创建一个具有更好自动调整大小功能的新 Canvas 类。在测量期间,您需要测量子元素并相应地调整 Canvas 的大小。您可能会发现这样的课程对您很有帮助。
这是一篇关于WPF中自动布局的文章。
如果你想创建一个自定义面板,这里有一个子主题:自定义面板元素。
编辑:还有一件事:您还可以将子元素的宽度/高度绑定到画布上的 ActualWidth 和 ActualHeight 属性,以便子元素调整其父元素的大小。如有必要,您可以使用转换器设置尺寸比。
您是否尝试将所有内容(您的自定义控件内容)包装到 Viewbox 中?例如
<UserControl>
<Border BorderBrush="Black" BorderThickness="1">
<Viewbox>
<Grid>
<TextBlock Name="txtDefault" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" Foreground="Black" Opacity="0.5" Text="Default" />
<TextBlock Name="txtValue" FontSize="16" Foreground="Black" Visibility="Collapsed" />
<TextBlock Name="txtKey" Grid.Column="1" FontSize="18" Foreground="Black" Visibility="Collapsed" />
</Grid>
</Viewbox>
</Border>
</UserControl>
您需要覆盖控件的 MeasureOverride 方法并从那里返回所需的大小(画布的大小)。然后父控件将调整自身大小以适应它的子控件(如果可以的话)。
您可以使用 UniFormGrid 来归档它。将列或行设置为 1,以便您可以获得垂直/水平排列的项目
<UniformGrid Columns="1">
<Button Content="Content 1"/>
<Button Content="Content 2"/>
<Button Content="Content 3"/>
</UniformGrid>