2
votes

I have a wpf window with a grid. I would like to hide rows and I do with this code as shown in other stackoverflow threads:

            buttonsGrid.Visibility = Visibility.Collapsed; or buttonsGrid.Height = 0;
            dayTimePicker.Visibility = Visibility.Collapsed; or dayTimePicker.Height = 0;

Set Visibility to Collapsed or Height to 0 gives the same effect, but I would like the white space occupied by these Rows to sweep ... I would like the whole window to be occupied by the indexed row 0. .. How can I do it?

This is my window:

<Window x:Class="PerformanceVideoRec.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    xmlns:DTControl="clr-namespace:DayTimePickControl"
    Title="{StaticResource ID_TITLE}" Height="600" Width="900" Loaded="Window_Loaded"> <!--Closing="Window_Closing"> -->

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid Grid.Row="1" x:Name="ControlPart" IsEnabled="False">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="6*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0" x:Name="LeftGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="55*"/>
                <RowDefinition Height="5*"/>
                <RowDefinition Height="5*"/>
                <RowDefinition Height="20*"/>
            </Grid.RowDefinitions>
            <WindowsFormsHost Grid.Row="0" Margin="5" Background="Gray">
                <wf:PictureBox x:Name="playWindow"></wf:PictureBox>
            </WindowsFormsHost>
            <UniformGrid Grid.Row="1">
                <Button x:Name="btnShowHideControls" Content="Nascondi Controlli" Click="btnShowHideControls_Click"/>
            </UniformGrid>
            <UniformGrid Columns="6" Grid.Row="2" x:Name="buttonsGrid">
                <Button x:Name="btnPause" Margin="5" Width="50" Content="{StaticResource ID_PAUSE}" Click="btnPause_Click"></Button>
                <Button x:Name="btnPlay" Margin="5" Width="50" Content="{StaticResource ID_PLAY}" Click="btnPlay_Click"  Visibility="Collapsed"/>
                <Button x:Name="btnStop" Margin="5" Width="50" Content="{StaticResource ID_STOP}" Click="btnStop_Click"></Button>
                <Button x:Name="btnSlow" Margin="5" Width="50" Content="{StaticResource ID_SLOW}" Click="btnSlow_Click"></Button>
                <TextBox x:Name="tbSpeed" IsEnabled="False" Width="50" Height="25" TextAlignment="Center" VerticalContentAlignment="Center" Text="1X" />
                <Button x:Name="btnFast" Margin="5" Width="50" Content="{StaticResource ID_FAST}" Click="btnFast_Click"></Button>
                <Button x:Name="btnNormal" Margin="5" Width="50" Content="{StaticResource ID_NORMAL}" Click="btnNormal_Click"></Button>
            </UniformGrid>
            <DTControl:DayTimePick x:Name="dayTimePicker" Grid.Row="3" Width="550" Height="100" Grid.RowSpan="2" OnTimeClick="dayTimePicker_OnTimeClick"></DTControl:DayTimePick>
        </Grid>
        <Frame x:Name="PlayBackFrame" Grid.Column="1" Background="AliceBlue" ></Frame>

    </Grid>
</Grid>

3
It is not good practice to set Height to 0 when you want to collpapse a control.user5447154

3 Answers

2
votes

The MVVM way:

  • make a separate view model for the part of UI you want to collapse. Let's call it PlayViewModel,
  • make a DataTemplate for it,
  • expose it as a property (e.g. let's call it Play, don't forget to raise property change event) in the view model which is a DataContext for the whole view

  • you display it in your grid with ContentPresenter, ContentPresenter.Content bound to Play property

  • you do hiding by null-ing Play property, you show it by restoring it.

You get testability for free.

1
votes

You could use Data Binding and bind the the property Visibility of the control inside the row you want to collapse with a converter.

I usually use the NuGet package Mvvm Light, documentation to have some facilities while using Data Binding. (In this case RelayCommand, RaisePropertyChanged implementation)

A very basic example:

Part of the view. Here you can notice the Binding between the Visibility property of the button and the property IsButton1Visible of the ViewModel. Of course bool and Visibility aren't the same type, so I had to create a mapping using an IValueConverter:

 <Grid>

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

    <Button Grid.Row="0" Content="1" Visibility="{Binding IsButton1Visible, Converter={StaticResource BooleanToVisibilityConverter}}" />
    <Button Grid.Row="1" Content="2" />
    <Button Grid.Row="2" Content="3" />
    <Button Grid.Row="3" Content="4" />
    <Button Grid.Row="4" Content="Toggle button 1 visibility" Command="{Binding ToggleButton1Visibility}" />

</Grid>

The window's constructor in the code behind (you could also bind the ViewModel via the DataContext property directly into the View), used to associate the View with the ViewModel:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new MyWindowViewModel();
}

The converter to convert true to Visibility.Visible:

public class BooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => (bool)value ? Visibility.Visible : Visibility.Collapsed;

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

App.xaml, Application.Resource part, used to make the View "see" the converter:

<Application.Resources>

    <local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />

</Application.Resources>

The ViewModel. Here RaisePropertyChanged of set method of IsButton1Visible is very important because it notifies the View that the property is changed, so that the View can refresh itself:

public class MyWindowViewModel : ViewModelBase
{
    private bool _isButton1Visibile = true;
    public bool IsButton1Visible
    {
        get => _isButton1Visibile;
        set
        {
            if (_isButton1Visibile == value)
                return;

            _isButton1Visibile = value;
            RaisePropertyChanged(nameof(IsButton1Visible));
        }
    }


    RelayCommand _toggleButton1Visbility;
    public RelayCommand ToggleButton1Visibility
    {
        get
        {
            return _toggleButton1Visbility ?? (_toggleButton1Visbility = new RelayCommand(
                () =>
                {
                    IsButton1Visible = !IsButton1Visible;
                }));
        }
    }
}
-1
votes
LeftGrid.RowDefinitions[2].Height = new GridLength(0);
LeftGrid.RowDefinitions[3].Height = new GridLength(0);

If you want to restore make this

   LeftGrid.RowDefinitions[2].Height = new GridLength(5, GridUnitType.Star);
    LeftGrid.RowDefinitions[3].Height = new GridLength(20, GridUnitType.Star);