2012-10-25 8 views
6

Ich versuche, zwei Kontrollen haben die gleiche Höhe. Kann ich es nur mit XAML machen?Wie kann man die Kontrollhöhe auf die Höhe eines anderen Kontrollelements übertragen?

Wenn ich etwas wie <Canvas Height="{Binding Height, ElementName=AnotherControl}" /> gemacht habe, tut es eigentlich nichts und die Höhe geht auf Null. Das Bedienfeld "Ausgabe" meldet keine Bindungsfehler, sodass AnotherControl.Height tatsächlich vorhanden ist. Ich habe versucht, an ActualHeight zu binden, aber es tut auch nichts.

Alles andere, was ich verpasst habe?

+0

Gleicher Kommentar wie @Clemens, wenn Sie WinRT XAML verwenden, sollten Sie Ihr WPF-Tag entfernen –

Antwort

10

Meine Vermutung ist, dass Sie AnotherControl nicht explizit eine Height gegeben. Leider sind in WinRT (anders als WPF, aber gleich Silverlight) ActualWidth und ActualHeight sogenannte "berechnete Eigenschaften". Dies bedeutet, dass ein Ereignis mit geänderter Eigenschaft nicht intern ausgelöst wird, wenn sie sich ändert. Infolgedessen ist die Bindung an sie nicht zuverlässig, und wie Sie bemerkt haben, würde es nicht ganz funktionieren.

Seitennotiz: es kann von Zeit zu Zeit funktionieren, aber das ist rein wegen des Timings des Get-Aufrufs das bindende Framework macht zu ActualHeight.

So wie es steht, können Sie nicht tun es nur mit XAML. Sie müssen das ActualControl.SizeChanged-Ereignis in Code-Behind behandeln und das Height zu AnotherControl.ActualHeight explizit festlegen.

+0

Meine Motivation für das Ausführen in XAML ist, weil das Steuerelement in mehreren Ebenen von Elementvorlage ist und es möglicherweise teuer zu erreichen ist sie über den Code – xster

+0

Selbst wenn dies nur in XAML möglich wäre, wären die Kosten gleich. Die Binding-Engine macht dasselbe wie Sie ... Sie registriert ein Ereignis mit geänderter Eigenschaft für die Abhängigkeitseigenschaft/INPC-Eigenschaft und weist dann den Wert der Bindungsquelle dem Ziel zu. Sie replizieren das nur in Ihrem Code. –

6

Wie Kshitij Mehta erwähnt, ist die Bindung an ActualHeight und ActualWidth in WinRT nicht zuverlässig. Aber es gibt eine schöne Arbeit-around, wo Sie müssen das Sizechanged-Ereignis nicht verwenden:

diese Klasse hinzufügen:

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

Platz es in den Ressourcen:

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

und binden zu den Eigenschaften:

1

Diese Frage ist sehr alt, aber hier ist meine Lösung. Sie können diesen Code verwenden

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

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

ich es auf meinem Windows/Windows Phone 8.1 Geräte getestet haben und es workes groß.