Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - Columns don't hide properly when GridSplitter is moved

I'm trying to hide a column in a Grid with a GridSplitter when a button is clicked (the button sets the visibility of all items in the third column to collapsed). If I don't move the GridSplitter it works properly and the third column disappear, but if I move the GridSplitter the content disappear but the others columns don't resize to fill the empty space.

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

    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="a" Width="*"/>
        <ColumnDefinition x:Name="b" Width="3"/>
        <ColumnDefinition x:Name="c" Width="Auto" MaxWidth="600"/>
    </Grid.ColumnDefinitions>
    <Border Grid.Column="0" Grid.Row="0" HorizontalAlignment="Stretch" Background="Green">
        <Image Source="te/Dante.png" Height="Auto" Margin="0,128,2,71"/>
    </Border>
    <Button Grid.Column="0" Grid.Row="0" Width="30" Height="30" Margin="0,10,10,0" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Button_Click"></Button>
    <GridSplitter Width="5" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" ResizeDirection="Columns" HorizontalAlignment="Left" Background="White" BorderBrush="Black" BorderThickness="1,0" ResizeBehavior="PreviousAndCurrent"/>
    <WrapPanel x:Name="wpC" Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" MinWidth="300" HorizontalAlignment="Stretch" Background="Aqua" Panel.ZIndex="-1"></WrapPanel>
</Grid>

Here is an example of my problem (gif):

How can i solve this problem? Possibly respecting MVVM pattern.

like image 566
Jacopo Avatar asked May 04 '16 11:05

Jacopo


1 Answers

The problem is simple, you set GridSplitter ResizeBehavior="PreviousAndCurrent", but previous grid column width is * and as soon as you move splitter its width units will be changed to absolute (so it will not be able to resize when 3d column width is changed).

Simply set GridSplitter ResizeBehavior="PreviousAndNext" to solve the problem. If you do so the splitter will modify width of 3d column, but shouldn't touch first one anymore.

Btw, instead of using button and click event you can utilize ToggleButton (which IsChecked is bound to Visibility of container with content you want to hide), see this answer. Using converters with pure xaml view is better MVVM than the one with some code behind and x:Name.


Right, you have few layout problems, here is a complete solution:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <Border Background="Green" />
    <ToggleButton x:Name="toggleButton"
                  Width="30"
                  Height="30"
                  Margin="0,10,10,0"
                  HorizontalAlignment="Right"
                  VerticalAlignment="Top" />
    <Grid Grid.Column="1"
          Visibility="{Binding IsChecked, ElementName=toggleButton, Converter={StaticResource BooleanToVisibilityConverter}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="300"
                              MinWidth="300"
                              MaxWidth="600" />
        </Grid.ColumnDefinitions>
        <GridSplitter Width="5"
                      ResizeBehavior="CurrentAndNext" />
        <WrapPanel Grid.Column="1"
                   Background="Aqua" />
    </Grid>
</Grid>

No need for code-behind, get converter from here.

Point are: 1) put splitter inside hide-able container 2) setup grid columns to have * and fixed width (splitter doesn't work well with auto columns).

Demo:

like image 143
Sinatr Avatar answered Oct 26 '22 13:10

Sinatr