multi - WPF: Establecer el ancho(y la altura) como un valor porcentual
view uwp (7)
Digamos que quiero que un TextBlock
tenga su Width
igual al Width
del contenedor primario (es decir, se extienda de lado a lado) o un porcentaje de su Width
contenedor principal, ¿cómo puedo lograr esto en XAML
sin especificar valores absolutos?
Quiero hacer esto para que, si el contenedor Parent Container se expande más tarde (es '' Width
increased''), sus ''Elementos secundarios'' también se expandan automáticamente. (básicamente, como en HTML y CSS)
Implementación IValueConverter se puede utilizar. La clase de convertidor que toma la herencia de IValueConverter toma algunos parámetros como el value
(porcentaje) y el parameter
(ancho de los padres) y devuelve el valor de ancho deseado. En el archivo XAML, el ancho del componente se establece con el valor deseado:
public class SizePercentageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null)
return 0.7 * value.ToDouble();
string[] split = parameter.ToString().Split(''.'');
double parameterDouble = split[0].ToDouble() + split[1].ToDouble() / (Math.Pow(10, split[1].Length));
return value.ToDouble() * parameterDouble;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Don''t need to implement this
return null;
}
}
XAML:
<UserControl.Resources>
<m:SizePercentageConverter x:Key="PercentageConverter" />
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled"
Width="{Binding Converter={StaticResource PercentageConverter}, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualWidth}"
Height="{Binding Converter={StaticResource PercentageConverter}, ConverterParameter=0.6, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}">
....
</ScrollViewer>
La forma de estirarlo al mismo tamaño que el contenedor primario es usar el atributo:
<Textbox HorizontalAlignment="Stretch" ...
Esto hará que el elemento del cuadro de texto se extienda horizontalmente y llene todo el espacio principal horizontalmente (en realidad depende del panel principal que está utilizando, pero debería funcionar en la mayoría de los casos).
Los porcentajes solo se pueden usar con valores de celdas de cuadrícula, por lo que otra opción es crear una cuadrícula y colocar su cuadro de texto en una de las celdas con el porcentaje apropiado.
Normalmente, utilizaría un control de diseño integrado apropiado para su escenario (por ejemplo, use una cuadrícula como elemento principal si desea escalar en relación con el elemento principal). Si desea hacerlo con un elemento primario arbitrario, puede crear un ValueConverter, pero probablemente no será tan limpio como desee. Sin embargo, si realmente lo necesita, podría hacer algo como esto:
public class PercentageConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
return System.Convert.ToDouble(value) *
System.Convert.ToDouble(parameter);
}
public object ConvertBack(object value,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Que se puede usar así, para obtener un cuadro de texto secundario al 10% del ancho de su lienzo principal:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<local:PercentageConverter x:Key="PercentageConverter"/>
</Window.Resources>
<Canvas x:Name="canvas">
<TextBlock Text="Hello"
Background="Red"
Width="{Binding
Converter={StaticResource PercentageConverter},
ElementName=canvas,
Path=ActualWidth,
ConverterParameter=0.1}"/>
</Canvas>
</Window>
Para cualquiera que obtenga un error como: la cadena ''2 *'' no puede convertirse a Longitud.
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" /><!--This will make any control in this column of grid take 2/5 of total width-->
<ColumnDefinition Width="3*" /><!--This will make any control in this column of grid take 3/5 of total width-->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="30" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0">Your text block a:</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="0">Your text block b:</TextBlock>
</Grid>
Sé que no es Xaml, pero hice lo mismo con el evento SizeChanged del cuadro de texto:
private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
TextBlock textBlock = sender as TextBlock;
FrameworkElement element = textBlock.Parent as FrameworkElement;
textBlock.Margin = new Thickness(0, 0, (element.ActualWidth / 100) * 20, 0);
}
El cuadro de texto parece tener un tamaño del 80% de su elemento primario (el margen derecho es 20%) y se estira cuando es necesario.
Yo uso dos métodos para el tamaño relativo. Tengo una clase llamada Relative
con tres propiedades adjuntas To
, WidthPercent
y HeightPercent
que es útil si quiero que un elemento sea un tamaño relativo de un elemento en cualquier parte del árbol visual y se siente menos hacky que el enfoque del convertidor, aunque use lo que funciona para tú, con quien estás feliz.
El otro enfoque es bastante más astuto. Agregue un ViewBox
donde desee tamaños relativos dentro, luego dentro de eso, agregue un Grid
en el ancho 100. Luego, si agrega un TextBlock
con ancho 10 dentro de eso, obviamente es 10% de 100.
El ViewBox
escalará la Grid
acuerdo con el espacio que se le haya asignado, de modo que si es lo único en la página, la Grid
se ampliará a todo su ancho y efectivamente, su TextBlock
se escalará al 10% de la página.
Si no establece una altura en la Grid
, se encogerá para ajustarse a su contenido, por lo que tendrá un tamaño relativamente grande. Deberá asegurarse de que el contenido no sea demasiado alto, es decir, que comience a cambiar la relación de aspecto del espacio dado al ViewBox
sino que también comenzará a escalar la altura. Probablemente puedas evitar esto con un Stretch
of UniformToFill
.
Esta es una respuesta actualizada a mi publicación anterior del ''09 y que contenía información incorrecta. El siguiente ejemplo debería ser mejor:
Puede colocar los cuadros de texto dentro de una cuadrícula para hacer valores porcentuales en las filas o columnas de la cuadrícula y dejar que los cuadros de texto se llenen automáticamente a sus celdas principales (como lo harán de forma predeterminada). Ejemplo:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" />
<TextBox Grid.Column="1" />
</Grid>
Esto hará # 1 2/5 del ancho, y # 2 3/5.
Publicación original con información incorrecta / incompleta
No creas que puedes hacer%, pero puedes hacerlo * :)
Ejemplo:
<TextBox width="2*"/>
<TextBox width="3*"/>
Esto hará # 1 2/5 del ancho, y # 2 3/5.