【问题标题】:How to databind control height to another control's height?如何将控件高度数据绑定到另一个控件的高度?
【发布时间】:2012-10-16 04:01:31
【问题描述】:

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

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

还有什么我错过的吗?

【问题讨论】:

  • 与@Clemens 相同的注释,如果你使用 WinRT XAML,你应该删除你的 WPF 标签

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


【解决方案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 设备上对其进行了测试,效果很好。

【讨论】:

    【解决方案2】:

    正如 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}"  />
    

    【讨论】:

      【解决方案3】:

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

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

      就目前而言,您不能仅使用 XAML 来做到这一点。您必须在代码隐藏中处理ActualControl.SizeChanged 事件,并将Height 显式设置为AnotherControl.ActualHeight

      【讨论】:

      • 我想要在 XAML 中执行此操作的动机是因为控件位于项目模板的多个层中,并且通过代码获取它们可能会很昂贵
      • 即使这仅在 XAML 中可行,成本也是一样的。绑定引擎执行与您相同的操作...它在依赖属性/INPC 属性上注册属性更改事件,然后将绑定源中的值分配给目标。你只是在你的代码中复制它。
      猜你喜欢
      • 2011-01-15
      • 2018-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      相关资源
      最近更新 更多