问题
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.
回答1:
Your problem is that Canvas panels do not resize to fit their content.
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.
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.
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.
The StackPanel type does not autosize at all in the dimension in which it is oriented, but it will autosize in the other dimension.
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.
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.
Here's an article on Auto Layout in 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.
回答2:
did you try to wrap everything (your custom control contents) into a Viewbox? eg
<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>
回答3:
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).
回答4:
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="1">
<Button Content="Content 1"/>
<Button Content="Content 2"/>
<Button Content="Content 3"/>
</UniformGrid>
来源:https://stackoverflow.com/questions/518674/force-a-custom-wpf-control-to-resize-correctly