Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I databind a ColumnDefinition's Width or RowDefinition's Height?

Under the View-Model-ViewModel pattern for WPF, I am trying to databind the Heights and Widths of various definitions for grid controls, so I can store the values the user sets them to after using a GridSplitter. However, the normal pattern doesn't seem to work for these particular properties.

Note: I'm posting this as a reference question that I'm posting as Google failed me and I had to work this out myself. My own answer to follow.

like image 473
Nidonocu Avatar asked Sep 29 '08 08:09

Nidonocu


2 Answers

Create a IValueConverter as follows:

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

You can then utilize the converter in your Binding:

<UserControl.Resources>     <local:GridLengthConverter x:Key="gridLengthConverter" /> </UserControl.Resources> ... <ColumnDefinition Width="{Binding Path=LeftPanelWidth,                                    Mode=TwoWay,                                   Converter={StaticResource gridLengthConverter}}" /> 
like image 174
Greg Sansom Avatar answered Sep 19 '22 09:09

Greg Sansom


There were a number of gotchas I discovered:

  1. Although it may appear like a double in XAML, the actual value for a *Definition's Height or Width is a 'GridLength' struct.
  2. All the properties of GridLength are readonly, you have to create a new one each time you change it.
  3. Unlike every other property in WPF, Width and Height don't default their databinding mode to 'TwoWay', you have to manually set this.

Thusly, I used the following code:

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

And the XAML:

<Grid.RowDefinitions>     <RowDefinition Height="*" MinHeight="100" />     <RowDefinition Height="Auto" />     <RowDefinition Height="{Binding Path=HorizontalInputRegionSize,Mode=TwoWay}" MinHeight="50" /> </Grid.RowDefinitions> 
like image 30
Nidonocu Avatar answered Sep 21 '22 09:09

Nidonocu