WPF: impostazione della larghezza (e dell'altezza) come valore percentuale


150

Supponiamo che io voglia TextBlockche abbia il suo Widthuguale al suo contenitore Genitore Width(cioè, allunga da un lato all'altro) o una percentuale del suo Contenitore Genitore Width, come posso farlo XAMLsenza specificare valori assoluti?

Voglio farlo in modo che se il contenitore Contenitore padre viene successivamente espanso (il suo " Widthaumentato " ), anche i suoi "Elementi figlio verranno espansi automaticamente. (sostanzialmente, come in HTML e CSS)


Dai un'occhiata a questa risposta .
Jesper Fyhr Knudsen,

Usa la risposta di cwap e includi la tb in un'impostazione della griglia che l'allineamento deve allungare.
Shimmy Weitzhandler,

Risposte:


91

Il modo per allungarlo alle stesse dimensioni del contenitore padre è utilizzare l'attributo:

 <Textbox HorizontalAlignment="Stretch" ...

Ciò allungherà l'elemento Textbox in senso orizzontale e riempirà tutto lo spazio padre in senso orizzontale (in realtà dipende dal pannello padre che stai usando ma dovrebbe funzionare nella maggior parte dei casi).

Le percentuali possono essere utilizzate solo con i valori delle celle della griglia, quindi un'altra opzione è quella di creare una griglia e inserire la casella di testo in una delle celle con la percentuale appropriata.


222

È possibile inserire le caselle di testo all'interno di una griglia per eseguire valori percentuali sulle righe o sulle colonne della griglia e lasciare che le caselle di testo si riempiano automaticamente nelle celle principali (come per impostazione predefinita). Esempio:

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

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

Questo farà # 1 2/5 della larghezza e # 2 3/5.


7
L'ho già provato, ma visualizzo questo errore: la stringa '2 *' non può essere convertita in lunghezza. '
Andreas Grech,

6
In realtà, * (Asterisco) è una piccola stella;) etymonline.com/index.php?term=asterisk
Deoghare

73
Mia mamma dice che sono una star
Denys Wessels,

7
Questo non funziona, anche se TextBox è in una griglia. La larghezza può essere impostata su Doppio, Doppio qualificato (un doppio valore seguito da px, in, cm o pt) o Auto. Vedi msdn.microsoft.com/en-GB/library/…
Darren,

2
Sì. Questa è in realtà una risposta molto scadente, ma sulla base di tutti gli voti, suppongo che abbia aiutato qualcuno (tanto tempo fa), motivo per cui non l'ho eliminato.
cwap

59

In genere, si utilizza un controllo di layout incorporato appropriato per il proprio scenario (ad esempio, utilizzare una griglia come genitore se si desidera ridimensionare rispetto al genitore). Se vuoi farlo con un elemento padre arbitrario, puoi creare un ValueConverter, ma probabilmente non sarà così pulito come vorresti. Tuttavia, se ne hai assolutamente bisogno, potresti fare qualcosa del genere:

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

Che può essere usato in questo modo, per ottenere una casella di testo figlio pari al 10% della larghezza della sua tela madre:

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

Questo è davvero fantastico, come posso farlo nel codice (impostare la larghezza della casella di testo)?
Jeremy,

9
Dovresti considerare di aggiungere CultureInfo.InvariantCulturealla doppia conversione perché parameterè considerato come stringe in culture diverse decimal separatornon funzionerà come previsto.
Appartamento Eric,

33

Per chiunque riceva un errore del tipo: la stringa '2 *' non può essere convertita in lunghezza.

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

Perché no <RowDefinition Height="auto" />?
Ben

2
"auto" occupa solo lo spazio necessario al controllo
Yama

Grazie mille, questa dovrebbe essere la risposta migliore.
Mafii,

Questa è sicuramente la risposta migliore.
Knut Valen,

7

L'implementazione di IValueConverter può essere utilizzata. La classe del convertitore che prende l'eredità da IValueConverter accetta alcuni parametri come value(percentuale) e parameter(larghezza del genitore) e restituisce il valore di larghezza desiderato. Nel file XAML, la larghezza del componente è impostata con quella desiderata con valore:

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>

4

So che non è Xaml ma ho fatto la stessa cosa con l'evento SizeChanged della casella di testo:

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 casella di testo sembra avere l'80% delle dimensioni del suo genitore (ben il margine destro è del 20%) e si allunga quando necessario.


4

Uso due metodi per il dimensionamento relativo. Ho una classe chiamata Relativecon tre proprietà associate To, WidthPercenteHeightPercent che è utile se voglio un elemento da una dimensione relativa di un qualsiasi punto elemento nell'albero del visivo e si sente meno hacky rispetto all'approccio convertitore - anche se l'uso ciò che funziona per voi, che si sei contento.

L'altro approccio è piuttosto più astuto. Aggiungi un punto in ViewBoxcui desideri dimensioni relative all'interno, quindi all'interno, aggiungi a Gridcon larghezza 100. Quindi se aggiungi a TextBlockcon larghezza 10 all'interno, è ovviamente il 10% di 100.

Il ViewBoxridimensionerà in Gridbase allo spazio che è stato assegnato, quindi se è l'unica cosa sulla pagina, Gridverrà ridimensionato a tutta larghezza ed efficacemente, il tuo TextBlockverrà ridimensionato al 10% della pagina.

Se non si imposta un'altezza su Grid, si restringerà per adattarsi al suo contenuto, quindi sarà tutto relativamente dimensionato. Dovrai assicurarti che il contenuto non diventi troppo alto, cioè inizi a cambiare le proporzioni dello spazio dato all'altro ViewBoxaltrimenti inizierà a ridimensionare anche l'altezza. Probabilmente puoi aggirare questo problema con un Stretchof UniformToFill.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.