2008-09-29 10 views
28

Unter dem View-Model-ViewModel-Muster für WPF versuche ich, die Höhen und Breiten verschiedener Definitionen für Gittersteuerelemente zu ermitteln, sodass ich die Werte speichern kann, die der Benutzer nach der Verwendung eines GridSplitters festlegt. Das normale Muster scheint jedoch für diese besonderen Eigenschaften nicht zu funktionieren.Wie kann ich die Höhe einer ColumnDefinition Breite oder RowDefinition ermitteln?

Hinweis: Ich poste dies als eine Referenzfrage, die ich poste, da Google mich fehlschlug und ich musste das selbst ausarbeiten. Meine eigene Antwort zu folgen.

Antwort

17

Es gab eine Reihe von gotchas ich entdecken:

  1. Obwohl es wie ein Doppel in XAML, der tatsächliche Wert für a * Definition der Höhe oder Breite ist eine 'GridLength' Struktur erscheinen.
  2. Alle Eigenschaften von GridLength sind schreibgeschützt, Sie müssen jedes Mal, wenn Sie es ändern, ein neues erstellen.
  3. Im Gegensatz zu allen anderen Eigenschaften in WPF haben Breite und Höhe ihren Databinding-Modus nicht standardmäßig auf 'TwoWay', Sie müssen dies manuell festlegen.

Thusly, ich den folgenden Code verwendet:

private GridLength myHorizontalInputRegionSize = new GridLength(0, GridUnitType.Auto) 
public GridLength HorizontalInputRegionSize 
{ 
    get 
    { 
     // If not yet set, get the starting value from the DataModel 
     if (myHorizontalInputRegionSize.IsAuto) 
      myHorizontalInputRegionSize = new GridLength(ConnectionTabDefaultUIOptions.HorizontalInputRegionSize, GridUnitType.Pixel); 
     return myHorizontalInputRegionSize; 
    } 
    set 
    { 
     myHorizontalInputRegionSize = value; 
     if (ConnectionTabDefaultUIOptions.HorizontalInputRegionSize != myHorizontalInputRegionSize.Value) 
     { 
      // Set the value in the DataModel 
      ConnectionTabDefaultUIOptions.HorizontalInputRegionSize = value.Value; 
     } 
     OnPropertyChanged("HorizontalInputRegionSize"); 
    } 
} 

Und das XAML:

<Grid.RowDefinitions> 
    <RowDefinition Height="*" MinHeight="100" /> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="{Binding Path=HorizontalInputRegionSize,Mode=TwoWay}" MinHeight="50" /> 
</Grid.RowDefinitions> 
+9

GridLength ist spezifisch für WPF und gehört daher nicht in die ViewModel-Ebene. –

+2

Ich denke, dass die Annahme "kein WPF in ViewModel" falsch ist, da WPF viele Konstrukte bezüglich MVVM-Muster hat, wie zum Beispiel die eigentliche Datenbindung. Man könnte sagen, "GridLength ist spezifisch für die VIEW", stattdessen (es sei denn, es ist Teil des Domain-Problems, wie in Anwendungen zur Datenvisualisierung, deren Zweck es ist, Dinge zu planen und anzuzeigen). Aber sicher ist es umstritten ... – heltonbiker

+0

@heltonbiker "GridLength ist spezifisch für die VIEW" ist genauer. es sei denn Ihre Geschäftslogik ist ausschließlich oder teilweise über UI-Layout (Design) –

4

Eine andere Möglichkeit, da man zwischen GridLength und int gebracht Umwandlung ist eine IValueConverter zu erstellen und verwenden Sie es beim Binden an Width. IValueConverter s auch Zwei-Wege-Bindung, weil sie beide ConvertTo() und ConvertBack() Methoden haben.

34

ein IValueConverter erstellen wie folgt:

public class GridLengthConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double val = (double)value; 
     GridLength gridLength = new GridLength(val); 

     return gridLength; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     GridLength val = (GridLength)value; 

     return val.Value; 
    } 
} 

Anschließend können Sie verwenden, um den Konverter in Ihre Bindung:

<UserControl.Resources> 
    <local:GridLengthConverter x:Key="gridLengthConverter" /> 
</UserControl.Resources> 
... 
<ColumnDefinition Width="{Binding Path=LeftPanelWidth, 
            Mode=TwoWay, 
            Converter={StaticResource gridLengthConverter}}" /> 
+0

Wenn Sie eine Lösung für sehr ähnliches Problem suchen, können Sie es hier finden: http://stackoverflow.com/questions/7660967/wpf-error-cannot -find-goveraging-Frameworkelement-für-Zielelement – dzendras

+0

Wpf hat bereits eine GridLengthConverter-Klasse. Wäre es möglich, es so zu benutzen, wie es ist? – heltonbiker

+4

@heltonbiker Leider implementiert GridLengthConverter ITypeConverter statt IValueConverter und kann daher nicht als WPF-Bindungskonvertierung verwendet werden. –

2

Die einfachste Lösung ist einfach String-Einstellungen für diese Eigenschaften verwenden, so dass WPF wird unterstützt sie automatisch mit GridLengthConverter ohne zusätzliche Arbeit.