如何将控制高度数据绑定到另一个控件的高度?

时间:2012-10-25 21:28:27

标签: xaml data-binding windows-runtime winrt-xaml

我正在尝试让2个控件具有相同的高度。我可以只使用XAML吗?

如果我做了类似<Canvas Height="{Binding Height, ElementName=AnotherControl}" />之类的事情,它实际上并没有做任何事情,而且高度变为零。输出面板不会抱怨任何绑定错误,因此AnotherControl.Height确实存在。我尝试绑定到ActualHeight但它也没有做任何事情。

我错过了什么?

3 个答案:

答案 0 :(得分:11)

我的猜测是AnotherControl没有明确给出Height。不幸的是,在WinRT中(与WPF不同,但与Silverlight相同),ActualWidthActualHeight被称为“计算属性”。这意味着属性更改事件在更改时不会在内部引发。因此,绑定它们并不可靠,正如您所注意到的那样,它不会起作用。

旁注:它可能会不时起作用,但这纯粹是因为绑定框架对ActualHeight进行了调用的时间。

就目前而言,不能仅使用XAML。您必须在代码隐藏中处理ActualControl.SizeChanged事件,并明确将Height设置为AnotherControl.ActualHeight

答案 1 :(得分:7)

正如Kshitij Mehta所说,在WinRT中绑定到ActualHeight和ActualWidth是不可靠的。但是有一个很好的解决方法,你不必使用SizeChanged-Event:

添加此课程:

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"));
        }
    }
}

将其放在资源中:

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

并绑定到其属性:

<TextBlock x:Name="tb1" Text="{Binding ActualWidthValue, ElementName=proxy}"  />

答案 2 :(得分:1)

这个问题很老了,但这是我的解决方案。 您可以使用此代码

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

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

我已在Windows / Windows Phone 8.1设备上对其进行了测试,效果很好。