WPF: définition de la largeur (et de la hauteur) en tant que valeur de pourcentage

Disons que je veux qu'un TextBlock ait son Width égal à son conteneur Parent Width (c'est-à-dire, étirer d'un côté à l'autre) ou un pourcentage de son conteneur Parent Width, Comment puis-je accomplir cela dans XAML sans spécifier de valeurs absolues?

Je veux faire ceci de sorte que si le conteneur de conteneur Parent est plus tard développé (son 'Width augmenté), ses ' éléments enfants seront également développés automatiquement. (fondamentalement, comme en HTML et CSS)

126
demandé sur Andrea Antonangeli 2009-04-04 19:55:13

7 réponses

Le chemin de l'étirer à la même taille que le conteneur parent est d'utiliser l'attribut:

 <Textbox HorizontalAlignment="Stretch" ...

Cela fera que L'élément Textbox s'étire horizontalement et remplira tout l'Espace parent horizontalement (en fait, cela dépend du panneau parent que vous utilisez mais devrait fonctionner dans la plupart des cas).

Les pourcentages ne peuvent être utilisés qu'avec les valeurs des cellules de la grille, une autre option consiste à créer une grille et à placer votre zone de texte dans l'une des cellules avec le pourcentage approprié.

82
répondu gcores 2009-04-04 16:24:10

Ceci est une réponse mise à jour à mon post précédent de '09 et qui contenait des informations incorrectes. L'exemple suivant devrait s'avérer meilleur:

Vous pouvez placer les zones de texte dans une grille pour faire des valeurs de pourcentage sur les lignes ou les colonnes de la grille et laisser les zones de texte remplir automatiquement leurs cellules parentes (comme elles le feront par défaut). Exemple:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" />
        <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>

    <TextBox Grid.Column="0" />
    <TextBox Grid.Column="1" />
</Grid>

Cela fera #1 2/5 de la largeur, et #2 3/5.

Message Original avec incorrect / Non complet informations

Ne pensez pas que vous pouvez faire%, mais vous pouvez faire*:)

Exemple:

<TextBox width="2*"/>
<TextBox width="3*"/>

Cela fera #1 2/5 de la largeur, et #2 3/5.

185
répondu cwap 2016-09-22 19:02:38

Généralement, vous utiliserez un contrôle de mise en page intégré approprié à votre scénario (par exemple, utilisez une grille en tant que parent si vous voulez mettre à l'échelle par rapport au parent). Si vous voulez le faire avec un élément parent arbitraire, vous pouvez créer un valueconverter, mais il ne sera probablement pas aussi propre que vous le souhaitez. Cependant, si vous en avez absolument besoin, vous pouvez faire quelque chose comme ceci:

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

Qui peut être utilisé comme ceci, pour obtenir une zone de texte enfant 10% de la largeur de son parent toile:

<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>
46
répondu kvb 2009-04-04 16:35:35

Pour quiconque obtient une erreur comme : '2*' la chaîne ne peut pas être convertie en longueur.

<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>
28
répondu Humble Coder 2014-12-08 05:44:08

Je sais que ce N'est pas Xaml mais j'ai fait la même chose avec L'événement SizeChanged de la zone de texte:

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

La zone de texte semble avoir une taille de 80% de son parent (la marge de droite est de 20%) et s'étire en cas de besoin.

4
répondu Crippeoblade 2009-04-05 12:20:00

J'utilise deux méthodes pour le dimensionnement relatif. J'ai une classe appelée Relative avec trois propriétés attachéesTo, WidthPercent et HeightPercent ce qui est utile si je veux qu'un élément soit une taille relative d'un élément n'importe où dans l'arbre visuel et se sent moins hacky que l'approche du convertisseur - bien qu'utiliser ce qui fonctionne pour vous, que vous êtes satisfait.

L'autre approche est un peu plus rusée. Ajoutez un ViewBox où vous voulez des tailles relatives à l'intérieur, puis à l'intérieur, ajoutez un Grid à la largeur 100. Alors si vous ajoutez un TextBlock avec une largeur 10 à l'intérieur, c'est évidemment 10% de 100.

Le ViewBox va mettre à l'échelle le Grid en fonction de l'espace qui lui a été donné, donc si c'est la seule chose sur la page, alors le Grid sera mis à l'échelle pleine largeur et effectivement, votre TextBlock est mis à l'échelle à 10% de la page.

Si vous ne définissez pas de hauteur sur le Grid, il se rétrécira pour s'adapter à son contenu, donc tout sera relativement dimensionné. Vous devrez vous assurer que le contenu ne devient pas trop grand, c'est-à-dire commence à changer le rapport d'aspect de l'espace donné au ViewBox sinon, il commencera également à mettre à l'échelle la hauteur. Vous pouvez probablement contourner cela avec un Stretch de UniformToFill.

4
répondu Luke Puplett 2013-07-30 10:50:53

L'implémentation IValueConverter peut être utilisée. La classe Converter qui prend l'héritage de IValueConverter prend certains paramètres comme value (Pourcentage) et parameter (largeur du parent) et renvoie la valeur de largeur désirée. Dans le fichier XAML, la largeur du composant est définie avec celle souhaitée avec la valeur:

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>
3
répondu Adem Catamak 2018-04-06 15:40:59