How to databind control height to another control&

2019-02-22 06:29发布

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?

3条回答
闹够了就滚
2楼-- · 2019-02-22 07:05

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.

查看更多
迷人小祖宗
3楼-- · 2019-02-22 07:06

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}"  />
查看更多
该账号已被封号
4楼-- · 2019-02-22 07:13

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.

查看更多
登录 后发表回答