Silverlight XAML绑定ElementName

时间:2011-04-07 17:51:05

标签: silverlight xaml binding

我有以下XAML:

            <sdk:Label Content="{Binding RefreshTextToggle, Converter={StaticResource enumToText}, ConverterParameter=ItemsOfInterest,FallbackValue='Please select items of interest to you'}" 
                       Style="{StaticResource StandardLabel}"
                       Height="{Binding ElementName=ItemsOfInterest,Path=Height}"/>

            <ListBox Name="ItemsOfInterest" 
                     ItemsSource="{Binding Path=ItemsOfInterest}" 
                     Margin="5"
                     MinHeight="25"
                     Width="250"
                     HorizontalAlignment="Left">

ItemsOfInterest的高度是动态的,等待其中有多少个元素。

任何人都能看到我在高度绑定方面做错了什么?它甚至没有与ItemsOfInterst相同的大小。

2 个答案:

答案 0 :(得分:5)

你应该绑定到ActualHeight,它指定它所安排的高度。高度属性允许您设置固定高度,但不会告诉您排列时的高度。

<小时/> 编辑:

实际上,这是一个带有Silverlight的known bug

你必须像这样使用SizeChanged事件:

<UserControl x:Class="SilverlightApplication3.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Button Content="Add Item" Click="Button_Click" />

        <ListBox x:Name="listBox1" Grid.Column="0" Grid.Row="1" VerticalAlignment="Top" SizeChanged="listBox1_SizeChanged" />
        <ListBox x:Name="listBox2" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" />

    </Grid>
</UserControl>

使用代码隐藏:

using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication3 {
    public partial class MainPage : UserControl {
        public MainPage() {
            InitializeComponent();
        }

        private int counter;

        private void Button_Click(object sender, RoutedEventArgs e) {
            this.counter++;
            this.listBox1.Items.Add(counter.ToString());
        }

        private void listBox1_SizeChanged(object sender, SizeChangedEventArgs e) {
            this.listBox2.Height = this.listBox1.ActualHeight;
        }
    }
}

你也可以把它包装成一个很好的附加行为。

<小时/> 编辑: 这是一种行为:

<UserControl x:Class="SilverlightApplication3.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SilverlightApplication3"
        mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Button Content="Add Item" Click="Button_Click" />

        <ListBox x:Name="listBox1" Grid.Column="0" Grid.Row="1" VerticalAlignment="Top" />
        <ListBox x:Name="listBox2" Grid.Column="1" Grid.Row="1" VerticalAlignment="Top" local:SizeSynchronizationBehavior.HeightElement="{Binding ElementName=listBox1}" />

    </Grid>
</UserControl>

使用代码隐藏:

using System;
using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication3 {
    public partial class MainPage : UserControl {
        public MainPage() {
            InitializeComponent();
        }

        private int counter;

        private void Button_Click(object sender, RoutedEventArgs e) {
            this.counter++;
            this.listBox1.Items.Add(counter.ToString());
        }
    }

    public static class SizeSynchronizationBehavior {

        #region Dependency Properties

        ///////////////////////////////////////////////////////////////////////////////////
        // HeightElement
        ///////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Identifies the <c>HeightElement</c> attached dependency property.  This field is read-only.
        /// </summary>
        /// <value>The identifier for the <c>HeightElement</c> attached dependency property.</value>
        public static readonly DependencyProperty HeightElementProperty = DependencyProperty.RegisterAttached("HeightElement",
            typeof(FrameworkElement), typeof(SizeSynchronizationBehavior), new PropertyMetadata(null, OnHeightElementPropertyValueChanged));

        /// <summary>
        /// Gets the value of the <see cref="HeightElementProperty"/> attached property for the specified <see cref="FrameworkElement"/>.
        /// </summary>
        /// <param name="obj">The object to which the attached property is retrieved.</param>
        /// <returns>
        /// The value of the <see cref="HeightElementProperty"/> attached property for the the specified <see cref="FrameworkElement"/>.
        /// </returns>
        public static FrameworkElement GetHeightElement(FrameworkElement obj) {
            if (obj == null) throw new ArgumentNullException("obj");
            return (FrameworkElement)obj.GetValue(HeightElementProperty);
        }

        /// <summary>
        /// Sets the value of the <see cref="HeightElementProperty"/> attached property to the specified <see cref="FrameworkElement"/>.
        /// </summary>
        /// <param name="obj">The object to which the attached property is written.</param>
        /// <param name="value">
        /// The new value of the <see cref="HeightElementProperty"/> attached property to the specified <see cref="FrameworkElement"/>.
        /// </param>
        public static void SetHeightElement(FrameworkElement obj, FrameworkElement value) {
            if (obj == null) throw new ArgumentNullException("obj");
            obj.SetValue(HeightElementProperty, value);
        }

        /// <summary>
        /// Called when <see cref="HeightElementProperty"/> is changed.
        /// </summary>
        /// <param name="d">The dependency object that was changed.</param>
        /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private static void OnHeightElementPropertyValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            FrameworkElement element = d as FrameworkElement;
            if (element == null)
                return;

            SizeChangedEventHandler heightSizeChangedEventHandler = GetSizeChangedEventHandler(element);
            if (heightSizeChangedEventHandler == null) {
                heightSizeChangedEventHandler = (sender, eventArgs) => {
                    FrameworkElement he = GetHeightElement(element);
                    if (he != null)
                        element.Height = he.ActualHeight;
                };
                SetSizeChangedEventHandler(element, heightSizeChangedEventHandler);
            }

            FrameworkElement heightElement = e.OldValue as FrameworkElement;
            if (heightElement != null)
                heightElement.SizeChanged += heightSizeChangedEventHandler;

            heightElement = e.NewValue as FrameworkElement;
            if (heightElement != null)
                heightElement.SizeChanged += heightSizeChangedEventHandler;

        }

        ///////////////////////////////////////////////////////////////////////////////////
        // SizeChangedEventHandler
        ///////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Identifies the <c>SizeChangedEventHandler</c> attached dependency property.  This field is read-only.
        /// </summary>
        /// <value>The identifier for the <c>SizeChangedEventHandler</c> attached dependency property.</value>
        private static readonly DependencyProperty SizeChangedEventHandlerProperty = DependencyProperty.RegisterAttached("SizeChangedEventHandler",
            typeof(SizeChangedEventHandler), typeof(SizeSynchronizationBehavior), new PropertyMetadata(null));

        /// <summary>
        /// Gets the value of the <see cref="SizeChangedEventHandlerProperty"/> attached property for the specified <see cref="FrameworkElement"/>.
        /// </summary>
        /// <param name="obj">The object to which the attached property is retrieved.</param>
        /// <returns>
        /// The value of the <see cref="SizeChangedEventHandlerProperty"/> attached property for the the specified <see cref="FrameworkElement"/>.
        /// </returns>
        private static SizeChangedEventHandler GetSizeChangedEventHandler(FrameworkElement obj) {
            if (obj == null) throw new ArgumentNullException("obj");
            return (SizeChangedEventHandler)obj.GetValue(SizeChangedEventHandlerProperty);
        }

        /// <summary>
        /// Sets the value of the <see cref="SizeChangedEventHandlerProperty"/> attached property to the specified <see cref="FrameworkElement"/>.
        /// </summary>
        /// <param name="obj">The object to which the attached property is written.</param>
        /// <param name="value">
        /// The new value of the <see cref="SizeChangedEventHandlerProperty"/> attached property to the specified <see cref="FrameworkElement"/>.
        /// </param>
        private static void SetSizeChangedEventHandler(FrameworkElement obj, SizeChangedEventHandler value) {
            if (obj == null) throw new ArgumentNullException("obj");
            obj.SetValue(SizeChangedEventHandlerProperty, value);
        }

        #endregion // Dependency Properties
    }

}

答案 1 :(得分:0)

我创建了一个简单的项目,可以复制您遇到的问题:

  1. 添加了一个列表框和按钮
  2. 将按钮挂钩到列表框的高度
  3. 将列表框高度设置为“自动”
  4. 创建另一个按钮,将随机数量的项目添加到列表框
  5. 在运行时,列表框会增长,但相关按钮不会增长。我现在正在努力确定失败的原因。

    <强>更新

    好吧,这不起作用的原因是Auto不返回任何可用于通过此绑定确定列表框高度的实际值。我尝试了其他所有方法来解决这个问题而没有成功在依赖绑定的同时看到这个问题的解决方案会很有趣。