2012-10-25 4 views
6

私は2つのコントロールを同じ高さにしようとしています。私はXAMLだけでそれを行うことはできますか?コントロールの高さを他のコントロールの高さにデータバインドする方法は?

もし私が<Canvas Height="{Binding Height, ElementName=AnotherControl}" />のようなことをしたら、それは実際には何もせず、高さは0になります。 AnotherControl.Heightが実際に存在するように、出力パネルはバインディングエラーについては不平を言っていません。 ActualHeightへのバインドを試みましたが、どちらもしません。

私が見逃したことはありますか?

+0

WinRT XAMLを使用している場合は、@Clemensと同じコメントを使用してください。 –

答えて

10

私の推測では、AnotherControlには明示的にHeightが与えられていません。残念ながら、WinRT(WPFと異なり、Silverlightと同じ)では、ActualWidthActualHeightが「計算されたプロパティ」と呼ばれています。つまり、変更されたプロパティ変更イベントは、内部的には発生しません。結果として、それらへのバインディングは信頼できず、気付いたように、それはうまくいかないでしょう。

サイドノート:これは時々動作するかもしれませんが、それは純粋にバインディングフレームワークを得るコールのタイミングのためにActualHeightになります。

だから、できません XAMLだけでそれを行う。コード体系でActualControl.SizeChangedイベントを処理し、HeightAnotherControl.ActualHeightに明示的に設定する必要があります。

+0

XAMLでこれをやりたいのは、コントロールがアイテムテンプレートの複数のレイヤーにあり、それらはコード – xster

+0

によって可能です。これがXAMLでのみ可能だったとしても、コストは同じになります。バインディングエンジンは同じことをします...依存関係プロパティ/ INPCプロパティにプロパティ変更イベントを登録し、バインディングソースの値を宛先に割り当てます。あなたはあなたのコードでそれを複製しています。 –

6

Kshitij Mehtaが述べたように、WinRTのActualHeightとActualWidthへのバインドは信頼できません。

このクラスを追加します:リソースで

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> 

とBINDをしかし、素敵な回避策、あなたはSizeChangedイベントを使用するために持っていけない存在でありますそのプロパティに:

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

この質問は非常に古いですが、ここに私のソリューションです。 あなたは私が私のWindows/Windows Phoneの8.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}"/> 

を使用することができますし、それは素晴らしいworkes。

関連する問題