Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to databind control height to another control's height?

I'm trying to have 2 controls have the same height. Can I do it with XAML only?

If I did something like <Canvas Height="{Binding Height, ElementName=AnotherControl}" /> it doesn't actually do anything and the height goes to zero. The Output panel doesn't complain about any binding errors so AnotherControl.Height really exists. I tried binding to ActualHeight but it doesn't do anything either.

Anything else I missed?

like image 652
xster Avatar asked Oct 25 '12 21:10

xster


3 Answers

My guess is that you AnotherControl is not explicitly given a Height. Unfortunately, in WinRT (unlike WPF, but the same as Silverlight), ActualWidth and ActualHeight are what are known as "calculated properties". This means that a property changed event doesn't internally get raised when they change. As a result, binding to them is not reliable, and as you've noticed, it wouldn't quite work.

Side note: it may work from time to time, but that is purely because of the timing of the get call the binding framework makes to ActualHeight.

So as it stands, you cannot do it with XAML only. You have to handle the ActualControl.SizeChanged event in code-behind, and set the Height to AnotherControl.ActualHeight explicitly.

like image 85
K Mehta Avatar answered Nov 08 '22 20:11

K Mehta


As Kshitij Mehta mentioned, binding to ActualHeight and ActualWidth in WinRT isnt reliable. But there is a nice work-around, where you dont have to use the SizeChanged-Event:

Add this class:

public class ActualSizePropertyProxy : FrameworkElement, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public FrameworkElement Element
    {
        get { return (FrameworkElement)GetValue(ElementProperty); }
        set { SetValue(ElementProperty, value); }
    }

    public double ActualHeightValue
    {
        get { return Element == null ? 0 : Element.ActualHeight; }
    }

    public double ActualWidthValue
    {
        get { return Element == null ? 0 : Element.ActualWidth; }
    }

    public static readonly DependencyProperty ElementProperty =
        DependencyProperty.Register("Element", typeof(FrameworkElement), typeof(ActualSizePropertyProxy),
                                    new PropertyMetadata(null, OnElementPropertyChanged));

    private static void OnElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ActualSizePropertyProxy)d).OnElementChanged(e);
    }

    private void OnElementChanged(DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement oldElement = (FrameworkElement)e.OldValue;
        FrameworkElement newElement = (FrameworkElement)e.NewValue;

        newElement.SizeChanged += new SizeChangedEventHandler(Element_SizeChanged);
        if (oldElement != null)
        {
            oldElement.SizeChanged -= new SizeChangedEventHandler(Element_SizeChanged);
        }
        NotifyPropChange();
    }

    private void Element_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        NotifyPropChange();
    }

    private void NotifyPropChange()
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("ActualWidthValue"));
            PropertyChanged(this, new PropertyChangedEventArgs("ActualHeightValue"));
        }
    }
}

Place it in the resources:

<UserControl.Resources>
    <c:ActualSizePropertyProxy Element="{Binding ElementName=YourElement}" x:Name="proxy" />
</UserControl.Resources>

And bind to its properties:

<TextBlock x:Name="tb1" Text="{Binding ActualWidthValue, ElementName=proxy}"  />
like image 33
Florian Gl Avatar answered Nov 08 '22 20:11

Florian Gl


This Question is very old, but here is my solution. You can use this Code

<!--First Button-->
<Button x:Name="button1" Height="50" Width="100"/>

<!--Second Button-->
<Button x:Name="button2" Height="50" Width="{Binding ElementName=button1, Path=Width}"/>

I've tested it on my Windows / Windows Phone 8.1 Device and it workes great.

like image 20
Matt126 Avatar answered Nov 08 '22 19:11

Matt126