What is the difference between Width and ActualWidth in WPF?
Width
/Height
is the requested or layout size. If you set to Auto, then the value is double.NaN
when you access the property in code behind.
ActualWidth
/ActualHeight
and RenderSize.Width
/RenderSize.Height
both return the element's rendered size, as RenderSize is of type Size. If you want/need the actual size of the item, then use any of these attributes.
I find ActualWidth
most useful when I want to bind the width or height of one element to another.
In this simple example I have two buttons arranged side by side and a comment underneath that is constrained to the width of the StackPanel containing the two buttons.
<StackPanel>
<StackPanel Margin="0,12,0,0" Orientation="Horizontal" Name="buttonPanel" HorizontalAlignment="Left" >
<Button Content="Yes - Arm the missile" FontWeight="Bold" HorizontalAlignment="Left"/>
<Button Content="No - Save the world" HorizontalAlignment="Left" Margin="7,0,0,0"/>
</StackPanel>
<TextBlock Text="Please choose whether you want to arm the missile and kill everybody, or save the world by deactivating the missile."
Width="{Binding Path=ActualWidth,ElementName=buttonPanel}" Margin="0,5,0,0" HorizontalAlignment="Left" TextWrapping="Wrap"/>
</StackPanel>
ActualWidth
accounts for padding in the value so anytime you need to know that number you can call Actualwidth
instead of width and avoid the calculation.
edit: removed Margin b/c it isn't part of ActualWidth.
There is a very good reason not to use the ActualWidth
to bind to (obviously ActualHeight
accordingly).
When you set the Width
of an element, to the ActualWidth
of another one you may break the layout chain.
In the best case your element/control needs to be parsed after the layout process of the parent (the binding source) finished. That means additional time. If it is at the same hierarchy level as the parent the layout process needs two runs (at least) to calculate a definitive size.
For example I had a control which had it's size property overridden in a style that would set it to the TemplatedParent
(don't do):
<Rectangle DockPanel.Dock="Top" Width="{TemplateBinding ActualWidth}"
Height="1" Fill="#000000"/>
When resizing the containing window, the control would prevent the container from becoming smaller and brake the layout. Setting it to the Width
will resolve the problem (do):
<Rectangle DockPanel.Dock="Top" Width="{TemplateBinding Width}"
Height="1" Fill="#000000"/>
If you have to use the ActualWidth
in general something is wrong with your xaml. Better fix that instead of messing up with the final sizes of the layout run.