Nascondi riga della griglia in WPF


94

Ho un semplice modulo WPF con una Griddichiarazione nel modulo. Questo Gridha un sacco di righe:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" MinHeight="30" />
    <RowDefinition Height="Auto" Name="rowToHide" />
    <RowDefinition Height="Auto" MinHeight="30" />
</Grid.RowDefinitions>

La riga denominata rowToHidecontiene alcuni campi di input e desidero nascondere questa riga dopo aver rilevato che non ho bisogno di questi campi. È abbastanza semplice impostare solo Visibility = Hiddentutti gli elementi nella riga, ma la riga occupa ancora spazio nel file Grid. Ho provato a impostare Height = 0gli elementi, ma non sembra funzionare.

Puoi pensarlo in questo modo: hai un modulo, lì hai un menu a discesa che dice "Tipo di pagamento", e se la persona seleziona "Contanti", vuoi nascondere la riga contenente i dettagli della Carta. Non è un'opzione per avviare il modulo con questo già nascosto.


1
vedere questo suggerimento sulla visibilità essendo un sistema a 3 stati (nel thread dei suggerimenti WPF): stackoverflow.com/questions/860193/wpf-simple-tips-and-tricks/…
Metro Smurf

Roba geniale ... Se la mettessi come risposta, sottolineerei che ...
Richard

Risposte:


88

Row non ha una proprietà Visibility, quindi come altri hanno detto, è necessario impostare l'Altezza. Un'altra opzione è utilizzare un convertitore, nel caso in cui sia necessaria questa funzionalità in molte visualizzazioni:

    [ValueConversion(typeof(bool), typeof(GridLength))]
    public class BoolToGridRowHeightConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ((bool)value == true) ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {    // Don't need any convert back
            return null;
        }
    }

E poi nella vista appropriata <Grid.RowDefinition>:

<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>

10
UpVoted - I convertitori consentono che tutto questo sia dichiarativo in Xaml. In genere odio usare il code-behind per giocherellare con le cose visive.
Allen

1
Questo è abbastanza utile e può essere facilmente esteso. Suggerisco di chiamarlo BoolToGridLengthConvertere di aggiungere una VisibleLength-Property, per tornare (bool)value == true. È così che puoi anche riutilizzarlo con Autoe qualsiasi valore fisso.
LuckyLikey

1
Bella risposta. Presumo che tu intendessi IsDisplayedRow, non IsHiddenRow.
NielW

72

La soluzione migliore e pulita per comprimere righe o colonne è utilizzare un DataTrigger, quindi nel tuo caso:

<Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" MinHeight="30" />
      <RowDefinition Name="rowToHide">
        <RowDefinition.Style>
          <Style TargetType="{x:Type RowDefinition}">
            <Setter Property="Height" Value="Auto" />
            <Style.Triggers>
              <DataTrigger Binding="{Binding SomeBoolProperty}" Value="True">
                <Setter Property="Height" Value="0" />
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </RowDefinition.Style>
      </RowDefinition>
      <RowDefinition Height="Auto" MinHeight="30" />
    </Grid.RowDefinitions>
  </Grid>

5
Mi piace questo approccio perché non è necessario codice C # aggiuntivo.
user11909

1
Non dimenticare di implementarlo INotifyPropertyChangednel tuo codice sottostante affinché funzioni quando SomeBoolPropertyviene modificato :).
benichka

55

Puoi anche farlo facendo riferimento alla riga nella griglia e quindi modificando l'altezza della riga stessa.

XAML

<Grid Grid.Column="2" Grid.Row="1" x:Name="Links">
   <Grid.RowDefinitions>
      <RowDefinition Height="60" />
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
      <RowDefinition Height="80" />
   </Grid.RowDefinitions>
</Grid>

VB.NET

If LinksList.Items.Count > 0 Then
   Links.RowDefinitions(2).Height = New GridLength(1, GridUnitType.Star)
Else
   Links.RowDefinitions(2).Height = New GridLength(0)
End If

Sebbene funzioni anche il Collasso degli elementi all'interno della Griglia, questo è un po 'più semplice se hai molti elementi nella Griglia che non hanno un elemento che lo racchiude che può essere compresso. Ciò fornirebbe una buona alternativa.


2
Questo ha anche il vantaggio di lavorare con righe che utilizzano la notazione a stella!
Johny Skovdal

1
Farlo nel codice è la soluzione più chiara e leggibile. Forse aggiungi un commento dopo il RowDefinition, come<RowDefinition Height="*" /><!-- Height set in code behind -->
Kay Zed

2
Non credo che questa sia la soluzione più chiara e leggibile poiché il codice funzionale è diviso in due file separati. In effetti, tutto può essere fatto con XAML puro - vedi la mia risposta.
Lukáš Koten

Le mie esigenze erano leggermente diverse e in C #, ma questo esempio mi ha indirizzato nella giusta direzione. Grazie!
nrod

30

Per riferimento, Visibilityè un'enumerazione System.Windows.Visibility a tre stati :

  • Visibile: l'elemento viene visualizzato e partecipa al layout.
  • Compresso: l'elemento è invisibile e non partecipa al layout. Dandogli effettivamente un'altezza e una larghezza di 0 e comportandosi come se non esistesse.
  • Nascosto: l'elemento è invisibile ma continua a partecipare al layout.

Vedi questo suggerimento e altri suggerimenti nel thread WPF Tips and Tricks .


1
Impostare tutti gli elementi nella riga su Visibility.Collapsed ha funzionato, grazie.
Richard

1
Ho votato in basso perché penso che la risposta di @ TravisPUK contenga una soluzione più chiara e ovvia.
testpattern

11
@testpattern: i voti negativi vengono generalmente utilizzati per le risposte errate. Se l'altra risposta è migliore, votala semplicemente.
Metro Smurf

6
@MetroSmurf abbastanza giusto. Probabilmente, la tua risposta non è corretta perché RowDefinition non ha una proprietà per Visibility. TravisPUK mostra come nascondere una riga e questa dovrebbe essere la risposta accettata.
testpattern

8

Invece di giocherellare con la riga della griglia, è possibile impostare la proprietà Visibility dei controlli (campi nella riga) su "Collapsed". Questo assicurerà che i controlli non occupino spazio e se hai Grid Row Height = "Auto", la riga sarà nascosta poiché tutti i controlli nella riga hanno Visibility = "Collapsed".

<Grid>
       <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="Auto" Name="rowToHide" />
       </Grid.RowDefinitions>

   <Button Grid.Row=0 Content="Click Me" Height="20">
       <TextBlock Grid.Row=1 
Visibility="{Binding Converter={StaticResource customVisibilityConverter}}" Name="controlToHide"/>

</Grid>

Questo metodo è migliore perché la visibilità dei controlli può essere associata a una proprietà con l'aiuto di un convertitore.


7

Fai semplicemente questo:
rowToHide.Height = new GridLength(0);

se lo utilizzerai, visibility.Collapsedovrai impostarlo per ogni membro della riga.


6

Imposta la visibilità del contenuto della riga su Visibility.Collapsedinvece che su Nascosto. In questo modo il contenuto smetterà di occupare spazio e la riga si ridurrà in modo appropriato.


1
Ho visto da qualche altra parte che qualcuno ha menzionato la Row Visibility. Ma la riga non ha uno stato di visibilità? L'impostazione di visibilità per tutti gli elementi della riga, tuttavia, ha funzionato.
Richard

5
@Richard: non puoi impostare RowDefinition.Visibility poiché non è un UIElement, ma puoi mettere tutto il tuo contenuto per la riga (o ogni colonna all'interno della riga) in un singolo contenitore e impostare la visibilità di quel contenitore.
Reed Copsey

1
Cosa succede se la riga della griglia non ha alcun contenuto, ma un'altezza fissa? C'è un modo conveniente per mostrare / nascondere?
kevinarpe

4

Ho avuto un'idea simile ereditando RowDefinition (solo per interesse)

public class MyRowDefinition : RowDefinition
{
    private GridLength _height;

    public bool IsHidden
    {
        get { return (bool)GetValue(IsHiddenProperty); }
        set { SetValue(IsHiddenProperty, value); }
    }

    // Using a DependencyProperty as the backing store for IsHidden.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsHiddenProperty =
        DependencyProperty.Register("IsHidden", typeof(bool), typeof(MyRowDefinition), new PropertyMetadata(false, Changed));

    public static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var o = d as MyRowDefinition;
        o.Toggle((bool)e.NewValue);
    }

    public void Toggle(bool isHidden)
    {
        if (isHidden)
        {
            _height = this.Height;
            this.Height = new GridLength(0, GridUnitType.Star);
        }                                                     
        else
            this.Height = _height;
    }          
}

Ora puoi usarlo come segue:

 <Grid.RowDefinitions>
        <RowDefinition Height="2*" />
        <my:MyRowDefinition Height="4*" IsHidden="false" x:Name="RowToHide" />
        <RowDefinition Height="*" />
        <RowDefinition Height="60" />
    </Grid.RowDefinitions>

e alternare con

RowToHide.IsHidden = !RowToHide.IsHidden;
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.