WPF - Adopt size of parent

Ian picture Ian · May 31, 2012 · Viewed 37.4k times · Source

I'm trying to figure out the best way to size some controls but can't quite get it right. I have a window that adds on a custom control:

<Grid x:Name="LayoutRoot">
    <my:RateGraph Grid.Column="0" x:Name="rateGraph1" Height="88" Width="380" />
</Grid>

I then wish to size the sub-components of this control defined in the XAML to fill either the height, width or both. What I find however is that if I take off the explicit width/height and try and use something like VerticalAlignment="Stretch" then I get a control of size 0... What am I doing wrong?

<rb:RateBase x:Class="RateBar.RateGraph"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:rb="clr-namespace:RateBar"
             xmlns:sd="clr-namespace:System.Windows.Data"
             mc:Ignorable="d">
    <RangeBase.Resources>
        <rb:JScriptConverter x:Key="JScript" TrapExceptions="False"/>
        <ControlTemplate x:Key="rateGraphTemplate" TargetType="{x:Type rb:RateBase}">
            <Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <rb:Axis Width="320" Height="88"/>
                <Rectangle Height="88" Fill="#9690EE90" x:Name="progress">
                    <Rectangle.Width>
                        <MultiBinding Converter="{StaticResource JScript}" ConverterParameter="values[0]/values[1]*values[2]">
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Width"/>
                        </MultiBinding>
                    </Rectangle.Width>
                </Rectangle>
                <Polygon Fill="#FF06B025" x:Name="graph" />
                <Label Canvas.Left="0" Width="380" HorizontalContentAlignment="Right" Foreground="Black" Content="{Binding Path=Caption, RelativeSource={RelativeSource TemplatedParent}}">
                    <Canvas.Bottom>
                        <MultiBinding Converter="{StaticResource JScript}" ConverterParameter="(values[2]*0.8)/values[1]*values[0]">
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Rate"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="RateMaximum"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Height"/>
                        </MultiBinding>
                    </Canvas.Bottom>
                </Label>
                <Line X1="0" X2="380" Stroke="Black">
                    <Canvas.Bottom>
                        <MultiBinding Converter="{StaticResource JScript}" ConverterParameter="(values[2]*0.8)/values[1]*values[0]">
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Rate"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="RateMaximum"/>
                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Height"/>
                        </MultiBinding>
                    </Canvas.Bottom>
                </Line>
            </Canvas>
        </ControlTemplate>
    </RangeBase.Resources>
</rb:RateBase>

Answer

Ross picture Ross · May 31, 2012

The Width and Height properties are primarily designed for setting requested dimensions.

If you are using dynamic layouts with stretching, etc. bind to the ActualWidth and ActualHeight properties:

<Binding RelativeSource="{RelativeSource ...}" Path="ActualWidth"/>