Simple Behavior for Binding to ActualWidth\ActualHeight

December 22, 2014

no comments

There are times when you want two or more elements in your XAML to share the same dimensions, usually you dint want to deal with static sizes and prefer that after an element got its size from the layout, all the other elements will be set to the same size.

you can find the real sizes of an element quite easily by looking at its ActualHeight and ActualWidth properties, however those properties doesn’t behave nice with binding and attempting to bind an element to another element ActualWidth\ActualHeight will result in an expected results.

to mitigate the problem I created a simple Behavior that enables binding to another element ActualHeight and ActualWidth

public class BindToActualDimensionBehavior : Behavior<FrameworkElement>
{
    public FrameworkElement SourceControl
    {
        get { return (FrameworkElement)GetValue(SourceControlProperty); }
        set { SetValue(SourceControlProperty, value); }
    }

    // Using a DependencyProperty as the backing store for SourceControl.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SourceControlProperty =
        DependencyProperty.Register("SourceControl", typeof(FrameworkElement), typeof(BindToActualDimensionBehavior), new PropertyMetadata(null, OnSourceControlChanged));

    private static void OnSourceControlChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {

        ((BindToActualDimensionBehavior)dependencyObject).OnSourceControlChanged((FrameworkElement)dependencyPropertyChangedEventArgs.OldValue, (FrameworkElement)dependencyPropertyChangedEventArgs.NewValue);
    }

    private void OnSourceControlChanged(FrameworkElement oldControl, FrameworkElement newControl)
    {
        if (oldControl!=null)
        {
            oldControl.LayoutUpdated -= OnSourceLayoutUpdated;
        }
        if (newControl!=null)
        {
            newControl.LayoutUpdated += OnSourceLayoutUpdated;
        }
    }
    public double ActualWidth
    {
        get { return (double)GetValue(ActualWidthProperty); }
        set { SetValue(ActualWidthProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ActualWidth.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ActualWidthProperty =
        DependencyProperty.Register("ActualWidth", typeof(double), typeof(BindToActualDimensionBehavior), new PropertyMetadata(0.0));

    

    public double ActualHeight
    {
        get { return (double)GetValue(ActualHeightProperty); }
        set { SetValue(ActualHeightProperty, value); }
    }

  

    // Using a DependencyProperty as the backing store for ActualHeight.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ActualHeightProperty =
        DependencyProperty.Register("ActualHeight", typeof(double), typeof(BindToActualDimensionBehavior), new PropertyMetadata(0.0));

   

    private void UpdateDimensions()
    {
        ActualHeight = SourceControl.ActualHeight;
        ActualWidth = SourceControl.ActualWidth;
    }

   

    void OnSourceLayoutUpdated(object sender, object e)
    {
       UpdateDimensions();
    }
}

in your XAML you will use it like this (Windows Store Example):

<Image  Source="ms-appx:///Assets/SomeImage.png"
        x:Name="emptyStateImg"
        Margin="213,148,213,0">
    <interactivity:Interaction.Behaviors>
        <behaviors:BindToActualDimensionBehavior 
              SourceControl="{Binding ElementName=AnotherImage}"
              ActualHeight="{Binding ElementName=emptyStateImg, Path=MaxHeight,Mode=TwoWay}" />
    </interactivity:Interaction.Behaviors>
</Image>
Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*