Home > front end >  GridSplitter with a fixed panel (grid column) when grid (usercontrol/window) size changes
GridSplitter with a fixed panel (grid column) when grid (usercontrol/window) size changes

Time:01-19

Basically, I want to emulate the GridSplitter.FixedPanel feature available in WinForms.

XAML :

<UserControl ...>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4*" />
            <ColumnDefinition Width="3" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <ListBox Grid.Column="0" />
        <GridSplitter 
            Grid.Column="1" Width="3" VerticalAlignment="Stretch" 
            Background="Transparent" 
            ResizeDirection="Columns" ResizeBehavior="PreviousAndNext" />
        <ListBox Grid.Column="2" />
    </Grid>
</UserControl>

This works great and resizes each side accordingly. But suppose we resize the (not maximized) window containing this UserControl, now both grid columns on each side of the splitter (auto) resizes. The 4/5 and 1/5 column width ratios are required for space distribution upon start, but practical space allocation depends on the displayed data, hence the grid splitter.

How to make one column retain its width (the one on the right for instance as it hosts properties, tools, etc.) while the window gets resized around, hence only making the left column resize.

I have some ideas :

  1. Just code behind to emulate FixedPanel like in WinForms : DragStarted, DragCompleted and some private fields for eg.
  2. Use a Behavior like suggested in this SO topic (I have not used Behaviors for years, have some refreshing to do - To be honest, I really hope there is an XAML-only way, but if there isn't, I prefer the code behind way where I expose new dependency propertie(s) rather than a behavior)
  3. I believe I'm missing one feature of WPF to achieve this the WPF way. Almost all times I thought "well I guess I have to code behind this...", there were the WPF way, usually simplier, safer, easy to design and better, performance wise. That's why I'm asking directly, and maybe would help someone else looking for the feature.

Programming language (for that matter) : C#


Edit : after Léo Savador's answer :

See : there were a WPF way (toying with XAML ColumnDefinition Width properties) and little code :

bool p_layoutInitialized = false;
void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) {
    if (e.NewSize.Width > 1) { // optional : && e.NewSize.Height > 1
        if (!p_layoutInitialized) {
            RightColumn.Width = new GridLength(MainGrid.ActualWidth / 5);
            p_layoutInitialized = true;
        }
    }
}

where RightColumn is the name of the ColumnDefinition on the right, and MainGrid the name of the Grid.

Thanks you so much, was in the process of writing heavy code behind. You saved me so much time :D


PS : Please do not assume I'm a WinForm fanboy. I'm only mentionning WinForms to give a comparative example of the desired feature, could have used CSS and JS, but much harder to describe.

CodePudding user response:

Here is a simple solution that I can recommend to you for your need:

For your right column, instead of using a dynamic width (1*), use a fixed width:

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="3" />
            <ColumnDefinition Width="160" />
        </Grid.ColumnDefinitions>

If you set a fixed width of 160:

  • You will get the same initial result (1/5 of the initial width of your window)
  • You will be still able to resize your grid
  • On resize, your right column will keep it's width

And you have also the possibility to use code behind to calculate the desired fixed width at startup, according to the window initial width, to be more "dynamic".

  •  Tags:  
  • Related