WPFでグリッド行を非表示にする


94

フォームでGrid宣言された単純なWPFフォームがあります。これGridにはたくさんの行があります:

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

という名前の行rowToHideにはいくつかの入力フィールドが含まれており、これらのフィールドが不要であることを検出した後、この行を非表示にしたいと思います。Visibility = Hidden行のすべてのアイテムに設定するだけの簡単な方法ですが、行はのスペースを占有しますGrid。設定Height = 0してみたのですがうまくいかないようです。

次のように考えることができます。フォームがあり、そこに「支払いの種類」というドロップダウンがあり、ユーザーが「現金」を選択した場合、カードの詳細を含む行を非表示にします。これをすでに非表示にしてフォームを開始することはできません。


1
(WPF先端スレッドで)3ステートシステムである可視性にこのヒントを参照してください。stackoverflow.com/questions/860193/wpf-simple-tips-and-tricks/...
メトロスマーフ

すばらしいもの...答えとしてそれを書き留めておくとしたら、それをマークします...
Richard

回答:


88

行にはVisibilityプロパティがないため、他の人が言ったように、高さを設定する必要があります。別のオプションは、多くのビューでこの機能が必要な場合にコンバーターを使用することです:

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

そして、適切なビューで<Grid.RowDefinition>

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

10
UpVoted-コンバーターは、Xamlでこれを宣言的にすることを許可します。私は通常、コードビハインドを使用して視覚的なものをいじるのが嫌いです。
アレン

1
これはかなり便利で、簡単に拡張できます。に戻るためにBoolToGridLengthConverter、それを呼び出してVisibleLength-Property を追加することをお勧めし(bool)value == trueます。これはAuto、任意のfix-Valueで再利用する方法でもあります。
LuckyLikey 2017

1
すばらしい答えです。IsHiddenRowではなく、IsDisplayedRowを意味していると思います。
NielW、2018年

72

行または列を折りたたむ最善かつクリーンなソリューションは、DataTriggerを使用することです。

<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
追加のC#コードが必要ないため、このアプローチが好きです。
user11909

1
変更されたINotifyPropertyChangedときに機能するように、コードビハインドに実装することを忘れないでくださいSomeBoolProperty
benichka 2018年

55

グリッドの行を参照し、行自体の高さを変更することによってもこれを行うことができます。

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

グリッド内の要素の折りたたみも機能しますが、折りたたむことができる囲んでいる要素がないグリッド内に多くの項目がある場合、これは少し単純です。これは良い代替手段となります。


2
これには、スター表記を使用する行を操作できるという利点もあります。
ジョニーSkovdal 2012

1
コードでこれを行うことが、最も明確で最も読みやすいソリューションです。おそらく、の後にコメントを追加します。RowDefinition<RowDefinition Height="*" /><!-- Height set in code behind -->
たとえば

2
機能コードは2つのファイルに分かれているため、これが最も明確で読みやすいソリューションだとは思いません。実際、それはすべて純粋なXAMLで実行できます-私の回答を参照してください。
ルカシュKoten

私のニーズは少し異なり、C#でしたが、この例は正しい方向を示しました。ありがとう!
nrod

30

参考までVisibilityに、次の3つの状態のSystem.Windows.Visibility列挙を示します。

  • 表示-要素がレンダリングされ、レイアウトに参加します。
  • 折りたたみ-要素は表示されず、レイアウトには関与しません。効果的に高さと幅を0に設定し、存在しないかのように動作します。
  • 非表示-要素は非表示ですが、引き続きレイアウトに参加しています。

WPFのヒントとトリックのスレッドで、このヒントとその他のヒントを参照してください。


1
行のすべての項目をVisibility.Collapsedに設定すると、ありがとうございます。
Richard

1
@TravisPUKの回答には、より明確で明確な解決策が含まれていると思うので、これに反対しました。
テストパターン2014

11
@testpattern-反対票は通常、不正解に使用されます。他の回答の方が良い場合は、賛成してください。
メトロスマーフ2014

6
@MetroSmurfは十分に公正です。おそらく、RowDefinitionにはVisibilityのプロパティがないため、答えは正しくありません。TravisPUKは行を非表示にする方法を示しており、これが受け入れられる答えです。
テストパターン

8

グリッド行をいじる代わりに、コントロール(行のフィールド)のVisibilityプロパティを "Collapsed"に設定できます。これにより、コントロールがスペースを取らないことが保証されます。GridRow Height = "Auto"の場合、行のすべてのコントロールに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>

コンバーターを使用してコントロールの可視性をいくつかのプロパティにバインドできるため、この方法の方が適しています。


7

単にこれを行う:
rowToHide.Height = new GridLength(0);

uが使用する場合visibility.Collapse、行のすべてのメンバーに対して設定する必要があります。


6

行のコンテンツの可視性をVisibility.Collapsed非表示ではなくに設定します。これにより、コンテンツがスペースを占有しなくなり、行が適切に縮小されます。


1
他の誰かが行の可視性について言及したのを見ました。しかし、ロウには可視性の状態がありませんか?行内のすべての項目をVisibility.Collapsedに設定しても機能しました。
Richard

5
@Richard:UIElementではないため、RowDefinition.Visibilityを設定することはできませんが、行(または行内の各列)のすべてのコンテンツを単一のコンテナーに入れ、そのコンテナーの可視性を設定できます。
リードコプシー、2010年

1
グリッド行にコンテンツがなく、高さが固定されている場合はどうなりますか?表示/非表示にする便利な方法はありますか?
kevinarpe

4

RowDefinitionを継承することで同様のアイデアを思いつきました

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

これで、次のように使用できます。

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

と切り替え

RowToHide.IsHidden = !RowToHide.IsHidden;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.