2012-10-25 8 views
6

Sto provando ad avere 2 controlli con la stessa altezza. Posso farlo solo con XAML?Come controllare l'altezza di controllo per l'altezza di un altro controllo?

Se ho fatto qualcosa come <Canvas Height="{Binding Height, ElementName=AnotherControl}" /> in realtà non fa nulla e l'altezza va a zero. Il pannello Output non si lamenta di eventuali errori di binding, quindi AnotherControl.Height esiste davvero. Ho provato a legare a ActualHeight ma non fa nulla.

Qualcos'altro che ho perso?

+0

Stesso commento di @Clemens, se si utilizza WinRT XAML, è necessario rimuovere il tag WPF –

risposta

10

La mia ipotesi è che al numero AnotherControl non sia stato assegnato un Height. Sfortunatamente, in WinRT (a differenza di WPF, ma uguale a Silverlight), ActualWidth e ActualHeight sono le cosiddette "proprietà calcolate". Ciò significa che un evento modificato proprietà non viene generato internamente quando cambiano. Di conseguenza, il loro legame non è affidabile e, come hai notato, non funzionerebbe affatto.

Nota a margine: può funzionare di volta in volta, ma questo è puramente a causa dei tempi della chiamata get che la struttura di binding rende a ActualHeight.

Allo stato attuale, non è possibile eseguire solo con XAML. È necessario gestire l'evento ActualControl.SizeChanged nel code-behind e impostare lo Height su AnotherControl.ActualHeight in modo esplicito.

+0

La mia motivazione per voler farlo in XAML è perché il controllo è in più livelli del modello di articolo e potrebbe essere costoso arrivare a tramite il codice – xster

+0

Anche se questo fosse possibile solo in XAML, il costo sarebbe lo stesso. Il motore di collegamento fa la stessa cosa che faresti ... Registra un evento modificato proprietà sulla proprietà di dipendenza/proprietà INPC e assegna quindi il valore dall'origine di associazione a destinazione. Lo stai semplicemente replicando nel tuo codice. –

6

Come menzionato da Kshitij Mehta, il collegamento a ActualHeight e ActualWidth in WinRT non è affidabile. Ma c'è un bel lavoro-around, dove non dovete utilizzare il SizeChanged-evento:

Aggiungi questa classe:

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

inserirlo nel risorse:

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

and BIND alle sue proprietà:

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

Questa domanda è molto vecchia, ma ecco la mia soluzione. È possibile utilizzare questo codice

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

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

ho provato sul mio Windows/Windows Phone 8.1 dispositivo ed è Workes grande.