Sembunyikan baris kisi di WPF

95

Saya memiliki formulir WPF sederhana dengan Gridpernyataan di formulir. Ini Gridmemiliki banyak baris:

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

Baris bernama rowToHideberisi beberapa bidang masukan dan saya ingin menyembunyikan baris ini setelah saya mendeteksi bahwa saya tidak memerlukan bidang ini. Cukup sederhana untuk hanya mengatur Visibility = Hiddenke semua item di baris, tetapi baris tersebut masih membutuhkan ruang di Grid. Saya mencoba mengatur Height = 0ke item, tetapi tampaknya tidak berhasil.

Anda dapat memikirkannya seperti ini: Anda memiliki formulir, di sana Anda memiliki drop-down bertuliskan "Jenis Pembayaran", dan jika orang tersebut memilih "Tunai", Anda ingin menyembunyikan baris yang berisi detail Kartu. Ini bukanlah pilihan untuk memulai formulir dengan ini sudah tersembunyi.

Richard
sumber
1
lihat tip ini pada Visibility sebagai sistem 3 negara (di utas tips WPF): stackoverflow.com/questions/860193/wpf-simple-tips-and-tricks/…
Metro Smurf
Hal-hal yang brilian ... Jika Anda meletakkannya sebagai jawaban, saya akan menandai bahwa ...
Richard

Jawaban:

88

Row tidak memiliki properti Visibility, jadi seperti yang dikatakan orang lain, Anda perlu mengatur Height. Pilihan lainnya adalah menggunakan konverter, jika Anda membutuhkan fungsionalitas ini di banyak tampilan:

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

Dan kemudian dalam tampilan yang sesuai <Grid.RowDefinition>:

<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>
pola pengujian
sumber
10
UpVoted - Pengonversi mengizinkan semua ini menjadi deklaratif di Xaml. Saya biasanya benci menggunakan kode di belakang untuk mengutak-atik hal-hal visual.
Allen
1
Ini sangat berguna dan dapat dengan mudah diperpanjang. Saya sarankan untuk memanggilnya BoolToGridLengthConverterdan menambahkan VisibleLength-Property, untuk kembali (bool)value == true. Itulah bagaimana Anda juga dapat menggunakannya kembali dengan Autodan Nilai-tetap apa pun.
LuckyLikey
1
Jawaban yang bagus. Saya berasumsi bahwa yang Anda maksud adalah IsDisplayedRow, bukan IsHiddenRow.
NielW
72

Solusi terbaik dan bersih untuk menciutkan baris atau kolom adalah dengan menggunakan DataTrigger, jadi dalam kasus Anda:

<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>
Lukáš Koten
sumber
5
Saya suka pendekatan ini karena Anda tidak memerlukan kode C # tambahan.
user11909
1
Jangan lupa untuk mengimplementasikan INotifyPropertyChangedkode Anda di belakangnya agar berfungsi saat SomeBoolPropertydiubah :).
benichka
55

Anda juga dapat melakukan ini dengan mereferensikan Baris dalam Petak dan kemudian mengubah Ketinggian baris itu sendiri.

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

Meskipun Penghilangan elemen di dalam Kotak juga berfungsi, ini sedikit lebih sederhana jika Anda memiliki banyak item di Kotak yang tidak memiliki elemen penutup yang dapat diciutkan. Ini akan menjadi alternatif yang baik.

TravisPUK
sumber
2
Ini juga memiliki keuntungan bekerja dengan baris yang menggunakan notasi bintang!
Johny Skovdal
1
Melakukan ini dalam kode adalah solusi yang paling jelas dan paling mudah dibaca. Mungkin tambahkan komentar setelah RowDefinition, seperti<RowDefinition Height="*" /><!-- Height set in code behind -->
Kay Zed
2
Saya rasa ini bukan solusi yang paling jelas dan paling mudah dibaca karena kode fungsional dibagi menjadi dua file terpisah. Sebenarnya itu semua bisa dilakukan dengan XAML murni - lihat jawaban saya.
Lukáš Koten
Kebutuhan saya sedikit berbeda dan dalam C # tetapi contoh ini mengarahkan saya ke arah yang benar. Terima kasih!
nrod
30

Untuk referensi, Visibilityadalah pencacahan System.Windows.Visibility tiga negara :

  • Terlihat - Elemen dirender dan berpartisipasi dalam tata letak.
  • Diciutkan - Elemen tidak terlihat dan tidak berpartisipasi dalam tata letak. Secara efektif memberikan tinggi dan lebar 0 dan berperilaku seolah-olah tidak ada.
  • Tersembunyi - Elemen tidak terlihat tetapi terus berpartisipasi dalam tata letak.

Lihat tip ini dan tip lainnya di utas Tip dan Trik WPF .

Metro Smurf
sumber
1
Mengatur semua Item di Baris ke Visibilitas. Diciutkan berfungsi, terima kasih.
Richard
1
Saya tidak menyukai ini karena menurut saya jawaban @ TravisPUK berisi solusi yang lebih jelas dan lebih jelas.
testpattern
11
@testpattern - suara negatif biasanya digunakan untuk jawaban yang salah. Jika jawaban lain lebih baik, cukup beri suara positif.
Metro Smurf
6
@Coklatklasikmlg Bisa dibilang, jawaban Anda tidak benar karena RowDefinition tidak memiliki properti untuk Visibilitas. TravisPUK menunjukkan cara menyembunyikan baris dan itu harus menjadi jawaban yang diterima.
testpattern
8

Daripada mengutak-atik Baris Kisi, Anda dapat menyetel properti Visibilitas Kontrol (bidang dalam baris) ke "Diciutkan". Ini akan memastikan bahwa kontrol tidak mengambil ruang apa pun dan jika Anda memiliki Tinggi Baris Kisi = "Otomatis", baris tersebut akan disembunyikan karena semua kontrol dalam baris memiliki 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>

Metode ini lebih baik karena Visibilitas kontrol dapat diikat ke beberapa properti dengan bantuan Konverter.

pengguna3726565
sumber
7

Cukup lakukan ini:
rowToHide.Height = new GridLength(0);

jika Anda akan menggunakan visibility.Collapsemaka Anda harus mengaturnya untuk setiap anggota baris.

NAMA PENGGUNA
sumber
6

Setel visibilitas konten baris ke Visibility.Collapseddaripada Tersembunyi. Ini akan membuat konten berhenti menghabiskan ruang, dan baris akan menyusut dengan semestinya.

Reed Copsey
sumber
1
Saya pernah melihat di tempat lain seseorang menyebutkan Visibilitas Baris. Tapi The Row tidak memiliki status visibilitas? Mengatur semua Item di Row menjadi Visibility. Collapsed berhasil.
Richard
5
@Richard: Anda tidak dapat menyetel RowDefinition.Visibility karena ini bukan UIElement - tetapi Anda dapat meletakkan semua konten Anda untuk baris (atau setiap kolom dalam baris) ke dalam satu wadah, dan mengatur visibilitas penampung itu.
Reed Copsey
1
Bagaimana jika baris kisi Anda tidak memiliki konten apa pun, tetapi tingginya tetap? Apakah ada cara yang mudah untuk menampilkan / menyembunyikan?
kevinarpe
4

Saya memiliki ide serupa dengan mewarisi RowDefinition (hanya untuk kepentingan)

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

Sekarang Anda dapat menggunakannya sebagai berikut:

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

dan beralih dengan

RowToHide.IsHidden = !RowToHide.IsHidden;
Matt
sumber