Приховати рядок сітки у WPF


94

У мене є проста форма WPF із Gridзаявленою формою. Це 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
дивіться цю пораду про Visibility як 3 державну систему (в потоці підказок WPF): stackoverflow.com/questions/860193/wpf-simple-tips-and-tricks/…
Metro Smurf

Блискучі речі ... Якби ви записали це як відповідь, я б це позначив ...
Річард

Погляньте і на цю підказку: social.msdn.microsoft.com/Forums/en-US/wpf/thread/…
Домокун

Відповіді:


88

Рядок не має властивості Видимість, тому, як казали інші, потрібно встановити Висоту. Іншим варіантом є використання перетворювача, якщо вам потрібна ця функціональність у багатьох представленнях:

    [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та будь-яке виправлене значення.
LuckyLikey

1
Чудова відповідь. Припускаю, ви мали на увазі IsDisplayedRow, а не IsHiddenRow.
NielW

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 07

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
Це також має перевагу роботи з рядками, що використовує позначення зірки!
Johny Skovdal

1
Робити це в коді - це найбільш чітке та читабельне рішення. Можливо, додайте коментар після RowDefinition, наприклад,<RowDefinition Height="*" /><!-- Height set in code behind -->
Kay Zed

2
Я не думаю, що це найяскравіше і найчитабельніше рішення, оскільки функціональний код розділений на два розділені файли. Насправді все це можна зробити за допомогою чистого XAML - див. Мою відповідь.
Lukáš Koten

Мої потреби були дещо іншими і в C #, але цей приклад вказував мені у правильному напрямку. Дякую!
nrod

30

Для довідки Visibility- це тридержавне перерахування System.Windows.Visibility :

  • Видимий - елемент відображається та бере участь у компонуванні.
  • Collapsed - Елемент невидимий і не бере участі у компонуванні. Ефективно даючи йому висоту і ширину 0 і поводячи себе так, ніби його немає.
  • Прихований - Елемент невидимий, але продовжує брати участь у макеті.

Ознайомтеся з цією порадою та іншими порадами з теми Поради та рекомендації WPF .


1
Призначення всіх елементів у рядку видимості. Згорнуте спрацювало, дякую.
Річард

1
Я спростував це, тому що думаю, що відповідь @ TravisPUK містить більш чітке і очевидне рішення.
тестпатерн

11
@testpattern - низькі голоси зазвичай використовуються для невірних відповідей. Якщо інша відповідь краще, просто підкресліть її.
Метро Смурф

6
@MetroSmurf досить справедливо. Можливо, ваша відповідь неправильна, оскільки RowDefinition не має властивості Visibility. TravisPUK показує, як приховати рядок, і це має бути прийнятою відповіддю.
testpattern

8

Замість того, щоб сповзати з Grid Row, ви можете встановити для властивості 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);

якщо ви будете використовувати, visibility.Collapseто вам доведеться встановити його для кожного члена ряду.


6

Встановіть для рядка видимість вмісту Visibility.Collapsedзамість Прихований. Це призведе до того, що вміст перестане займати місце, і рядок буде відповідно стискатися.


1
Я ще десь бачив, щоб хтось згадував видимість рядків. Але рядок не має стану видимості? Налаштування всіх елементів у рядку видимості. Згорнуте спрацювало.
Річард

5
@Richard: Ви не можете встановити RowDefinition.Visibility, оскільки це не UIElement - але ви можете помістити весь вміст для рядка (або кожного стовпця в рядку) в один контейнер і встановити видимість цього контейнера.
Рід Копсі,

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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.