Cómo Establecer la Columna de la Cuadrícula MaxWidth dependiendo de la Ventana o el Tamaño de la Pantalla en XAML
-
01-07-2019 - |
Pregunta
Tengo un 3 columna de la cuadrícula en una ventana con un GridSplitter en la primera columna.Quiero establecer la MaxWidth de la primera columna a un tercio de la Ventana principal o en la Página Width
(o ActualWidth
) y prefiero hacerlo en XAML, si es posible.
Esta es una muestra de la XAML para jugar en XamlPad (o similar) que muestra lo que estoy haciendo.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1" Width="200"/>
<ColumnDefinition x:Name="Column2" MinWidth="50" />
<ColumnDefinition x:Name="Column3" Width="{ Binding ElementName=Column1, Path=Width }"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Background="Green" />
<GridSplitter Grid.Column="0" Width="5" />
<Label Grid.Column="1" Background="Yellow" />
<Label Grid.Column="2" Background="Red" />
</Grid>
</Page>
Como se puede ver, la columna de la derecha anchura está obligado a que el ancho de la primera columna, así que cuando usted se desliza la columna de la izquierda utilizando el divisor, la columna de la derecha hace lo mismo :) Si desliza la columna de la izquierda a la derecha, que finalmente no se deslice más de la mitad de la página o de la ventana y a la derecha de la ventana, empujando lejos de la columna 2 y 3.
Quiero evitar esto mediante el ajuste de la MaxWidth de la columna 1 a un tercio de la anchura de la ventana (o algo así).Puedo hacer esto en el código detrás con bastante facilidad, pero ¿cómo hacerlo en "Sólo XAML"?
EDITAR: David Schmitt sugiere utilizar SharedSizeGroup en vez de encuadernación, que es una excelente sugerencia.Mi código de ejemplo de esto sería entonces:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1" SharedSizeGroup="ColWidth" Width="40"/>
<ColumnDefinition x:Name="Column2" MinWidth="50" Width="*" />
<ColumnDefinition x:Name="Column3" SharedSizeGroup="ColWidth"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Background="Green" />
<GridSplitter Grid.Column="0" Width="5" />
<Label Grid.Column="1" Background="Yellow" />
<Label Grid.Column="2" Background="Red" />
</Grid>
</Page>
Solución
Creo que el enfoque de XAML sólo es un poco tortuoso, pero aquí es una manera de hacerlo.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<!-- This contains our real grid, and a reference grid for binding the layout-->
<Grid x:Name="Container">
<!-- hidden because it's behind the grid below -->
<Grid x:Name="LayoutReference">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- We need the border, because the column doesn't have an ActualWidth -->
<Border x:Name="ReferenceBorder"
Background="Black" />
<Border Background="White" Grid.Column="1" />
<Border Background="Black" Grid.Column="2" />
</Grid>
<!-- I made this transparent, so we can see the reference -->
<Grid Opacity="0.9">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column1"
MaxWidth="{Binding ElementName=ReferenceBorder,Path=ActualWidth}"/>
<ColumnDefinition x:Name="Column2"
MinWidth="50" />
<ColumnDefinition x:Name="Column3"
Width="{ Binding ElementName=Column1, Path=Width }"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Background="Green"/>
<GridSplitter Grid.Column="0" Width="5" />
<Label Grid.Column="1" Background="Yellow" />
<Label Grid.Column="2" Background="Red" />
</Grid>
</Grid>
</Page>
Otros consejos
Demasiado perezoso para escribir que yo, pero usted debería ser capaz de utilizar un matemático del convertidor y se unen a su padre windows ancho (ya sea por nombre, o con un RelativeSource antepasado de búsqueda).
//I know I borrowed this from someone, sorry I forgot to add a comment from whom
public class ScaledValueConverter : IValueConverter
{
public Object Convert(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture)
{
Double scalingFactor = 0;
if (parameter != null)
{
Double.TryParse((String)(parameter), out scalingFactor);
}
if (scalingFactor == 0.0d)
{
return Double.NaN;
}
return (Double)value * scalingFactor;
}
public Object ConvertBack(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}