Posts Simple Behavior for Binding to ActualWidth or ActualHeight
Post
Cancel

Simple Behavior for Binding to ActualWidth or ActualHeight

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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):

1
2
3
4
5
6
7
8
9
<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>
This post is licensed under CC BY 4.0 by Tamir Dresher.

Trending Tags