2013-05-01 13 views
8

Stavo guardando this question e ho scoperto qualcosa di molto strano: sembra che l'altezza di una riga non sia calcolata correttamente in alcuni casi che riguardano Grid.RowSpan.Perché questo spazio extra appare in una griglia?

Ecco un semplice disegno del Grid sto testando con:

 
--------------- 
| 1 |  | 
--------| 3 | 
| 2 |  | 
--------------- 
|  4  | 
--------------- 

Ed ecco alcuni esempi di codice per questa griglia che illustra il problema:

<Grid ShowGridLines="True"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 

    <StackPanel Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Background="Red"> 
     <Label Content="CELL 1 A"/> 
     <Label Content="CELL 1 B"/> 
     <Label Content="CELL 1 C"/> 
    </StackPanel> 

    <Grid Grid.Column="0" Grid.Row="2" Background="CornflowerBlue"> 
     <Label Content="CELL 2 D"/> 
    </Grid> 

    <StackPanel Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" Background="Yellow"> 
     <Label Content="CELL 3 A"/> 
     <Label Content="CELL 3 B"/> 
     <Label Content="CELL 3 C"/> 
     <Label Content="CELL 3 D"/> 
    </StackPanel> 


    <Grid Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" Background="Green"> 
     <Label Content="CELL 4"/> 
    </Grid> 
</Grid> 

Il risultato finale è l'altezza della terza riga (cella n. 2 e n. 3) ha un sacco di spazio in più:

enter image description here

Se aggiusto il Grid.RowSpan della 1a e 3a cella di +/- 1, e aggiusti lo Grid.Row per la 2a e la 4a di +/- 1 per contabilizzare per la riga supplementare, ottengo questo risultato (corretto):

enter image description here

ho anche ottenere risultati corretti se rimuovere elementi sufficienti dalla cella # 3 in modo che possa rendere in una singola riga, in questo modo:

enter image description here

e stranamente, rimozione di alcuni il gli oggetti risultano solo in s ome dello spazio extra viene applicato

enter image description here

Sono stato nei guai con il numero di elementi in celle # 1 e # 3, e il numero di righe, ma io non riesco a capire un schema conclusivo per spiegare questo comportamento.

Che cosa esattamente fa WPF dietro le quinte quando si esegue il rendering di questa griglia per far sì che lo spazio extra appaia quando lo Grid.RowSpan sulla cella n.

+0

Stavo per dire perché una griglia misura in modo diverso ma l'ho provato con tutti gli stackpanel e le dimensioni sono errate. – Paparazzi

+0

Ci sono troppe altezze di riga 'Auto'. Il controllo Grid fa un buon lavoro nell'affrontare lo spanning di righe e colonne, ma quando tutte le altezze di riga sono impostate su 'Auto' è come risolvere un'equazione con troppe incognite. Vincolare 1 o entrambe le prime 2 file a un'altezza fissa aiuta immensamente. – Stewbob

+0

@Stewbob Ho anche provato a lasciare l'ultima riga a 'Height =" * "', e non fa differenza. Il problema è nel determinare l'altezza di una cella che usa 'RowSpan', e non è legata al modo in cui' Grid' alloca lo spazio verticale extra. Ho aggiornato il mio esempio di codice per includere una riga di dimensioni '*' per renderlo chiaro :) – Rachel

risposta

0

Non ho una risposta completa sul motivo per cui .NET non funziona correttamente nella terza riga.
Ma io sostengo che quello che chiedi di fare è illogico in quanto non vi è motivo di avere 0,0 span su due righe.
Quando le righe sono condivise, non è probabile che siano di uguale lunghezza e WPF deve aggiungere la lunghezza al più breve (i).
In questo caso poiché sono state condivise le righe nelle righe condivise in modo che WPF debba applicare una ponderazione e non farlo correttamente.
Se non si estendono 0 0, allora condivide lo spazio extra in più con la riga 0 colonna 0 e la riga 1 colonna 0 uguali che (per me) è la risposta corretta.

<Window x:Class="GridRowSizing.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <Style BasedOn="{StaticResource {x:Type Label}}" TargetType="Label"> 
      <Setter Property="BorderBrush" Value="Black"/> 
      <Setter Property="BorderThickness" Value="1"/> 
      <Setter Property="Margin" Value="3"/> 
     </Style> 
    </Window.Resources> 
    <Grid ShowGridLines="True"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <StackPanel Grid.Column="0" Grid.Row="0" Background="Red"> 
      <Label Content="CELL 1 A"/> 
      <Label Content="CELL 1 B"/> 
      <Label Content="CELL 1 C" BorderBrush="Black" BorderThickness="2"/> 
     </StackPanel> 
     <StackPanel Grid.Column="0" Grid.Row="1" Background="CornflowerBlue"> 
      <Label Content="CELL 2 D" BorderBrush="Black" BorderThickness="2"/> 
      <Label Content="CELL 2 E" BorderBrush="Black" BorderThickness="2"/> 
     </StackPanel> 
     <StackPanel Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Background="Yellow"> 
      <Label Content="CELL 3 A"/> 
      <Label Content="CELL 3 B"/> 
      <Label Content="CELL 3 C"/> 
      <Label Content="CELL 3 D" BorderBrush="Black" BorderThickness="2"/> 
      <Label Content="CELL 3 E" BorderBrush="Black" BorderThickness="2"/> 
      <Label Content="CELL 3 F" BorderBrush="Black" BorderThickness="2"/> 
     </StackPanel> 
     <StackPanel Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" Background="Green"> 
      <Label Content="CELL 4"/> 
     </StackPanel> 
    </Grid> 
</Window> 
+0

Sì, so che tale codice è illogico e che ci sono modi semplici per evitare tale comportamento, come rimuovere la 2a riga non necessaria e non definita (Grid.Row = "1"), ma ero curioso di sapere cosa WPF fa dietro le quinte di decidi di renderlo in questo modo in primo luogo e solo con specifici RowSpans. Sospetto che tu abbia ragione sul fatto che WPF stia applicando una certa ponderazione in modo errato quando misuri la riga non definita, dal momento che il numero di elementi influenza la quantità di spazio extra che viene pescato. Immagino che avrò bisogno di estrarre il riflettore per ottenere una risposta definitiva su questo ... – Rachel

+1

Sospetto che la ponderazione sia errata (ma non c'è una ragione valida che possa vedere per farla pesare). Dove vedi quello che sembra essere il peso corretto sospetto che il delta sia 0 e che ponderando 0 sbagliato non vedi la risposta sbagliata. – Paparazzi

1

Ho incontrato questo tipo di condizione prima, come in my question here su spazio extra appearing in a ListView

Per una risposta che ho ricevuto da un dipendente Microsoft:

Il bug comporta un passo nell'algoritmo di misurazione VSP che ricorda la dimensione maggiore mai scoperta e impone a tutte le future chiamate Measure di riportare una dimensione almeno altrettanto grande. Nel tuo caso, il VSP viene inizialmente misurato prima che vengano attivati ​​tutti i trigger, quindi calcola le dimensioni come se tutto fosse visibile.Quando i trigger attivano e comprimono i pulsanti, l'algoritmo di misurazione calcola la dimensione corretta (piccola), ma poi forza nuovamente il risultato.

Il comportamento della griglia appare simile al comportamento della mia Virtualizzazione pila di riquadri: Qualcosa sta succedendo con le chiamate di misura s' il RowDefinition che costringono a ricordare e riferire sempre una dimensione più grande, anche se in seguito verso il basso la linea più piccola sarebbe meglio.

In breve, probabilmente hai trovato un bug in WPF, che, poiché ci sono una miriade di soluzioni (abbinare le righe totali definite al totale necessario, riorganizzare la griglia, qualsiasi altra cosa ...) potrebbe non attirare mai l'attenzione. Puoi confermare o confutare questo solo aprendo un bug di Microsoft Connect e aspettando la loro risposta.

+2

Il post che hai collegato era molto interessante, e sospetto che tu abbia ragione sul fatto che sia un bug nelle chiamate Measure. Spero non ti dispiaccia, ma ho intenzione di modificare la tua risposta un po 'per includere la citazione relativa dal tuo post collegato. Speravo che qualcuno avrebbe postato una risposta spiegando esattamente cosa succede dietro le quinte per fare in modo che ciò accadesse, supportato da reflector o codice MSDN, ma non sembra che succederà così ti sto assegnando il rappresentante di taglie come penso la tua risposta è la cosa più vicina che otterrò a una risposta solida. – Rachel

+0

Rachel Penso che tu abbia appena dimostrato il valore di un buon editor. Random House, prendi nota! –

0

Come ha detto Rob, questo è probabilmente un bug nelle chiamate di misurazione WPF. Quindi non conosco la tua risposta. Ma per esplorare il funzionamento interno delle app WPF, io uso Snoop. È uno strumento fantastico, simile agli strumenti del browser che mostrano elementi HTML, snoop mostra come il tuo modulo WPF è strutturato, elementi nidificati, proprietà di elementi, ecc. Mi aiuta molto quando cerco di capire i problemi di layout. Ho pensato di menzionare.

Problemi correlati