.net 强制自定义 WPF 控件正确调整大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/518674/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force a custom WPF Control to resize correctly
提问by Scott
I have written a WPF user control and part of it involves dynamically adding elements to a canvas which effects the height of said canvas. The canvas is nested within a grid. When I dynamically add my elements the height of the canvas changes, but the canvas ends up extending beyond the edge of the overall control rather than causing the control to resize and make itself taller. How can I force the control to resize correctly? I get the feeling I need to either call or override Measure or Arrange but I'm having no luck with either method – possibly because I'm calling them with incorrect parameters or possibly because they aren't the correct methods to be calling.
我编写了一个 WPF 用户控件,其中一部分涉及将元素动态添加到画布,从而影响所述画布的高度。画布嵌套在网格中。当我动态添加元素时,画布的高度会发生变化,但画布最终会延伸到整个控件的边缘之外,而不是导致控件调整大小并使自身变高。如何强制控件正确调整大小?我觉得我需要调用或覆盖 Measure 或Arrange,但我对这两种方法都不走运——可能是因为我用不正确的参数调用它们,或者可能是因为它们不是正确的调用方法。
回答by Josh G
Your problem is that Canvas panels do not resize to fit their content.
您的问题是 Canvas 面板不会调整大小以适合其内容。
You refered to Measure and Arrange. Are you familiar with WPF's two pass layout system? Read this article for more information: WPF's Layout System.
您参考了测量和排列。你熟悉WPF的两遍布局系统吗?阅读这篇文章了解更多信息:WPF 的布局系统。
This article also describes what different panels do for layout. Each type of panel is different.
本文还介绍了不同面板对布局的作用。每种类型的面板都不同。
In WPF, elements are first given an opportunity to determine what size they will be. Panels can determine their size based on the size of their children, or they can ask for fixed size regardless of the size of their children. Canvas is an example of the latter.
在 WPF 中,元素首先有机会确定它们的大小。面板可以根据他们孩子的大小来确定他们的大小,或者他们可以要求固定的大小而不管他们孩子的大小。Canvas 是后者的一个例子。
Elements are next told what size they will be and asked to arrange themselves and their children.
元素接下来会被告知它们的大小,并要求他们安排自己和他们的孩子。
The Grid panel type not only allows rows and columns, but is also very good at auto sizing to content.
Grid 面板类型不仅允许行和列,而且还非常擅长根据内容自动调整大小。
The StackPanel type does not autosize at all in the dimension in which it is oriented, but it will autosize in the other dimension.
StackPanel 类型在它所面向的维度中根本不会自动调整大小,但它会在另一个维度中自动调整大小。
Canvas can auto size to fill a space, but it never allows it's children to auto size. It draws its children at the specified coordinates and does not care how big they are.
Canvas 可以自动调整大小以填充空间,但它永远不允许它的孩子自动调整大小。它在指定的坐标处绘制它的孩子,而不关心他们有多大。
I would suggest trying a Grid with only one row/column.
我建议尝试一个只有一行/列的网格。
Or you could create a new Canvas class that has better autosizing capabilities. During measure, you would want to measure the child elements and size your Canvas accordingly. You might find a class like this helpful down the road.
或者您可以创建一个具有更好的自动调整大小功能的新 Canvas 类。在测量期间,您可能希望测量子元素并相应地调整画布的大小。您可能会发现这样的课程很有帮助。
Here's an article on Auto Layoutin WPF.
这是一篇关于WPF 中自动布局的文章。
If you want to create a custom panel, here's a subtopic on it: Custom Panel Elements.
如果你想创建一个自定义面板,这里有一个关于它的子主题:自定义面板元素。
EDIT: One more thing: You can also bind the width/height of the child element to the ActualWidth and ActualHeight properties on the canvas so that the child will adjust the size of its parent. You can use a converter to set a size ratio if necessary.
编辑:还有一件事:您还可以将子元素的宽度/高度绑定到画布上的 ActualWidth 和 ActualHeight 属性,以便子元素调整其父元素的大小。如有必要,您可以使用转换器来设置大小比例。
回答by leion
did you try to wrap everything (your custom control contents) into a Viewbox? eg
您是否尝试将所有内容(您的自定义控件内容)包装到 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>
回答by Alan Mendelevich
You need to override MeasureOverride method of your control and return your desired size (the size of your canvas) from there. Then the parent control would resize itself to accommodate it's child (if it can).
您需要覆盖控件的 MeasureOverride 方法并从那里返回所需的大小(画布的大小)。然后父控件将调整自身大小以适应它的子控件(如果可以的话)。
回答by Jobi Joy
You can use a UniFormGrid to archive this. Set Columns or Row equals 1 so that you can get a vertical/horizontal arranged items
您可以使用 UniFormGrid 将其存档。设置 Columns 或 Row 等于 1,以便您可以获得垂直/水平排列的项目
<UniformGrid Columns="1">
<Button Content="Content 1"/>
<Button Content="Content 2"/>
<Button Content="Content 3"/>
</UniformGrid>

