Search code examples
wpflayoutexpandergridsplitter

How to use gridsplitter on dynamic layout?


For the life of me I can't get the gridsplitter control to behave in the way I want.

In the below layout, I need a gridspliter to the right of each listview, that will expand or contract that listview and resize the other listviews appropriately.

The expanders and their (green) panels should not resize.

Please help! This control is driving me nuts.

MainWindow.xaml:

<Window x:Class="LayoutTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window2" Height="400" MinWidth="1000">
    <Grid Name="root" SizeChanged="root_SizeChanged">
        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="200" Width="*" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition MinWidth="200" Width="*" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition MinWidth="200" Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <ListView Grid.Column="0" MinWidth="100">
            <ListViewItem>a</ListViewItem>
            <ListViewItem>b</ListViewItem>
            <ListViewItem>c</ListViewItem>
            <ListViewItem>d</ListViewItem>
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="a" Width="100" />
                    <GridViewColumn Header="b" Width="100" />
                    <GridViewColumn Header="c" Width="100" />
                    <GridViewColumn Header="d" Width="100" />
                </GridView>
            </ListView.View>
        </ListView>
        <Expander Name="xleft" Grid.Column="1" ExpandDirection="Left" Expanded="Expanded">
            <Border MinWidth="300"  Width="300" Background="Green" >
                <TextBlock Text="{Binding ElementName=root,Path=ActualWidth}" />
            </Border>
        </Expander>
        <ListView Grid.Column="2" MinWidth="100">
            <ListViewItem>a</ListViewItem>
            <ListViewItem>b</ListViewItem>
            <ListViewItem>c</ListViewItem>
            <ListViewItem>d</ListViewItem>
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="a" Width="100" />
                    <GridViewColumn Header="b" Width="100" />
                    <GridViewColumn Header="c" Width="100" />
                    <GridViewColumn Header="d" Width="100" />
                </GridView>
            </ListView.View>
        </ListView>
        <Expander Name="xmiddle" Grid.Column="3" ExpandDirection="Left" Expanded="Expanded">
            <Border MinWidth="300"  Width="300" Background="Green" >
                <TextBlock Text="{Binding ElementName=root,Path=ActualWidth}" />
            </Border>
        </Expander>
        <ListView Grid.Column="4" MinWidth="100">
            <ListViewItem>a</ListViewItem>
            <ListViewItem>b</ListViewItem>
            <ListViewItem>c</ListViewItem>
            <ListViewItem>d</ListViewItem>
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="a" Width="100" />
                    <GridViewColumn Header="b" Width="100" />
                    <GridViewColumn Header="c" Width="100" />
                    <GridViewColumn Header="d" Width="100" />
                </GridView>
            </ListView.View>
        </ListView>
        <Expander Name="xright" Grid.Column="5" ExpandDirection="Left" Expanded="Expanded">
            <Border MinWidth="300"  Width="300" Background="Green" >
                <TextBlock Text="{Binding ElementName=root,Path=ActualWidth}" />
            </Border>
        </Expander>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Controls;

namespace LayoutTest
{
    /// <summary>
    /// Interaction logic for Window2.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Expander[] expanders;
        Expander priority;

        public MainWindow()
        {
            InitializeComponent();
            expanders = new Expander[] {xleft,xmiddle,xright};
        }

        private void Expanded(object sender, RoutedEventArgs e)
        {
            if (sender is Expander) priority = sender as Expander;
            if (root.ActualWidth > this.ActualWidth)
            {
                foreach (Expander ep in expanders)
                {
                    if (ep.IsExpanded && priority != null && !ep.Name.Equals(priority.Name) )
                    {
                        ep.IsExpanded = false;
                        break;
                    }
                }
            }
        }

        private void root_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Expanded(null,new RoutedEventArgs());
        }
    }
}

Solution

  • It's not ideal, but this is the solution I'm going with:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" MinWidth="100" />
            <ColumnDefinition Width="Auto" />
    
            <ColumnDefinition Width="*" MinWidth="100" />
            <ColumnDefinition Width="Auto" />
    
            <ColumnDefinition Width="*" MinWidth="100" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Border Grid.Column="0" Background="Green">
        </Border>
        <Expander Name="ex1" Grid.Column="1" ExpandDirection="Left" Expanded="ex_Expanded">
            <Border Background="Blue" MinWidth="200" MaxWidth="200">
            </Border>
        </Expander>
        <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" ResizeBehavior="PreviousAndNext" VerticalAlignment="Stretch" Background="Red" />
        <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Right" ResizeBehavior="PreviousAndNext" VerticalAlignment="Stretch" Background="Red" />
        <Border Grid.Column="2" Background="Green">
        </Border>
        <Expander Name="ex2" Grid.Column="3" ExpandDirection="Left" Expanded="ex_Expanded">
            <Border Background="Blue" MinWidth="200" MaxWidth="200">
            </Border>
        </Expander>
        <GridSplitter Grid.Column="3" Width="5" HorizontalAlignment="Left" ResizeBehavior="PreviousAndNext" VerticalAlignment="Stretch" Background="Red" />
        <GridSplitter Grid.Column="3" Width="5" HorizontalAlignment="Right" ResizeBehavior="PreviousAndNext" VerticalAlignment="Stretch" Background="Red" />
        <Border Grid.Column="4" Background="Green">
        </Border>
        <Expander Name="ex3" Grid.Column="5" ExpandDirection="Left" Expanded="ex_Expanded">
            <Border Background="Blue" MinWidth="200" MaxWidth="200">
            </Border>
        </Expander>
    </Grid>