¿Cómo vinculo datos del ancho de una definición de columna o el alto de una definición de fila?
Bajo el patrón View-Model-ViewModel para WPF, estoy intentando vincular datos de alturas y anchos de varias definiciones para controles de cuadrícula, de modo que pueda almacenar los valores que el usuario establece después de usar un GridSplitter. Sin embargo, el patrón normal no parece funcionar para estas propiedades particulares.
Nota: Estoy publicando esto como una pregunta de referencia que estoy publicando porque Google me falló y tuve que resolverlo yo mismo. Mi propia respuesta a seguir.
Cree un IValueConverter
de la siguiente manera:
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;
}
}
Luego puede utilizar el convertidor en su enlace:
<UserControl.Resources>
<local:GridLengthConverter x:Key="gridLengthConverter" />
</UserControl.Resources>
...
<ColumnDefinition Width="{Binding Path=LeftPanelWidth,
Mode=TwoWay,
Converter={StaticResource gridLengthConverter}}" />
Descubrí una serie de trampas:
- Aunque puede parecer un doble en XAML, el valor real de la altura o el ancho de una *definición es una estructura 'GridLength'.
- Todas las propiedades de GridLength son de solo lectura, debe crear una nueva cada vez que la cambie.
- A diferencia de cualquier otra propiedad en WPF, Ancho y Alto no establecen su modo de enlace de datos predeterminado en 'TwoWay', debe configurarlo manualmente.
Por lo tanto, utilicé el siguiente código:
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");
}
}
Y el XAML:
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="100" />
<RowDefinition Height="Auto" />
<RowDefinition Height="{Binding Path=HorizontalInputRegionSize,Mode=TwoWay}" MinHeight="50" />
</Grid.RowDefinitions>
La solución más sencilla es simplemente usar configuraciones de cadena para estas propiedades para que WPF las admita automáticamente usando GridLengthConverter sin ningún trabajo adicional.