Mam prosty formularz WPF z Grid
zadeklarowanym w formularzu. To Grid
ma kilka wierszy:
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="30" />
<RowDefinition Height="Auto" Name="rowToHide" />
<RowDefinition Height="Auto" MinHeight="30" />
</Grid.RowDefinitions>
Wiersz o nazwie rowToHide
zawiera kilka pól wejściowych i chcę ukryć ten wiersz po wykryciu, że nie potrzebuję tych pól. Wystarczy ustawić Visibility = Hidden
wszystkie elementy w wierszu, ale wiersz nadal zajmuje miejsce w pliku Grid
. Próbowałem ustawić Height = 0
elementy, ale to nie działało.
Możesz o tym pomyśleć w ten sposób: Masz formularz, w którym masz listę rozwijaną z napisem „Rodzaj płatności”, a jeśli osoba wybierze opcję „Gotówka”, chcesz ukryć wiersz zawierający dane karty. Nie można już uruchomić formularza z tym ukrytym.
Odpowiedzi:
Wiersz nie ma właściwości Widoczność, więc jak powiedzieli inni, musisz ustawić wysokość. Inną opcją jest użycie konwertera, na wypadek gdybyś potrzebował tej funkcjonalności w wielu widokach:
[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; } }
A potem w odpowiednim widoku
<Grid.RowDefinition>
:<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>
źródło
BoolToGridLengthConverter
i dodaćVisibleLength
-Property, aby powrócić(bool)value == true
. W ten sposób możesz również użyć go ponownie zAuto
dowolną wartością ustaloną.Najlepszym i czystym rozwiązaniem zwinięcia wierszy lub kolumn jest użycie DataTrigger, więc w twoim przypadku:
<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>
źródło
INotifyPropertyChanged
w swoim kodzie, aby działał, gdySomeBoolProperty
zostanie zmieniony :).Możesz to również zrobić, odwołując się do wiersza w siatce, a następnie zmieniając wysokość samego wiersza.
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
Chociaż zwijanie elementów w siatce również działa, jest to nieco prostsze, jeśli masz wiele elementów w siatce, które nie mają otaczającego elementu, który można zwinąć. Stanowiłoby to dobrą alternatywę.
źródło
RowDefinition
, na przykład<RowDefinition Height="*" /><!-- Height set in code behind -->
Dla odniesienia
Visibility
jest to wyliczenie z trzema stanami System.Windows.Visibility :Zobacz tę wskazówkę i inne wskazówki w wątku Porady i wskazówki WPF .
źródło
Zamiast bawić się wierszem siatki, można ustawić właściwość Widoczność elementów sterujących (pól w wierszu) na „Zwinięty”. Zapewni to, że kontrolki nie zajmą miejsca i jeśli masz Wysokość wiersza siatki = „Auto”, wiersz zostanie ukryty, ponieważ wszystkie kontrolki w wierszu mają Widoczność = „Zwinięty”.
<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>
Ta metoda jest lepsza, ponieważ Widoczność kontrolek można powiązać z jakąś właściwością za pomocą konwertera.
źródło
Po prostu zrób to:
rowToHide.Height = new GridLength(0);
jeśli użyjesz,
visibility.Collapse
musisz ustawić to dla każdego członka wiersza.źródło
Ustaw widoczność zawartości wiersza
Visibility.Collapsed
zamiast Ukryte. Spowoduje to, że zawartość przestanie zajmować miejsce, a wiersz odpowiednio się zmniejszy.źródło
Miałem podobny pomysł, dziedzicząc RowDefinition (tylko dla zainteresowania)
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; } }
Teraz możesz go używać w następujący sposób:
<Grid.RowDefinitions> <RowDefinition Height="2*" /> <my:MyRowDefinition Height="4*" IsHidden="false" x:Name="RowToHide" /> <RowDefinition Height="*" /> <RowDefinition Height="60" /> </Grid.RowDefinitions>
i przełączaj z
RowToHide.IsHidden = !RowToHide.IsHidden;
źródło