WPF GridSplitter: How to move programmatically?
Asked Answered
A

3

10

I have two problems with the code below.

Problem 1) In the function MaximizePreview() I want to store the old width of the left column (lastListViewWidth = widthListView) and when calling MaximizeListView(), I want to restore the previous width of the left (and right) column. Therefore I write back the width I store with lastListViewWidth. The Problem is, that after restoring the width, the splitter does not exactly move to the old position. Calling both functions several times, the GridSplitter move more and more to the left and ListViewWith gets smaller with every call cycle. What do I have to do to exactly store and restore the GridSplitter's position and the width of the columns left and right from it?

Problem 2) You can see, that I added MinWidht="0.1", instead of MinWidth="0". The reason for that is, if a move the splitter absolutely to the right and than move the splitter to the left programmatically, the right column stays collapsed. If I move the splitter to the left by dragging it, the right column grows again when I move the splitter left. When setting MinWidth to 0.1 then moving the splitter left from the rightmost position programmatically works fine and the right column grows as when moving the splitter by hand. What is happening here?

I have defined the Grid as follows:

<Grid.ColumnDefinitions>
  <ColumnDefinition Width="*" Name="columnListView" />
  <ColumnDefinition Width="38" Name="columnSplitter"/>
  <ColumnDefinition Width="*" Name="columnPreView" MinWidth="0.1" />
</Grid.ColumnDefinitions>

I have to buttons/functions that move the GridSplitter programatically:

This function minimizes the left column.

private void MaximizePreview() {
  double widthPreview = columnPreView.ActualWidth;
  double widthSplitter = columnSplitter.ActualWidth;
  double widthListView = columnListView.ActualWidth;
  if(widthListView > 0) {
    lastListViewWidth = widthListView;
    columnListView.Width = new GridLength(0, GridUnitType.Star);
    columnPreView.Width = new GridLength(ActualWidth - widthSplitter, GridUnitType.Star);
  };
}

And with this function a want to restore the previous position.

private void MaximizeListView() {
  double widthPreview = columnPreView.ActualWidth;
  double widthSplitter = columnSplitter.ActualWidth;
  double widthListView = columnListView.ActualWidth;
  if(widthListView <= lastListViewWidth) {
    lastListViewWidth = Math.Min(lastListViewWidth, ActualWidth * .85);
    lastListViewWidth = Math.Max(lastListViewWidth, ActualWidth * .15);
    columnPreView.Width = new GridLength(ActualWidth - lastListViewWidth - widthSplitter, GridUnitType.Star);
    columnListView.Width = new GridLength(lastListViewWidth, GridUnitType.Star);
  };
}
Alviani answered 6/9, 2016 at 9:36 Comment(0)
T
13

You should set the parent container's grid/row definitions programatically:

Here's an example:

        private void GridRowSplitter_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        GridContent.RowDefinitions[0].Height = new GridLength(200, GridUnitType.Star);
        GridContent.RowDefinitions[1].Height = new GridLength(3, GridUnitType.Pixel);
        GridContent.RowDefinitions[2].Height = new GridLength(0,GridUnitType.Star);
    }
Tanker answered 25/6, 2018 at 14:9 Comment(0)
C
0

The problem 1) seems to be that your use of ActualWidth in MaximizeListView does not refer to the Grid, but to some parent element, which has a different width. If you instead use

private void MaximizeListView(object sender, RoutedEventArgs e)
{
    double widthPreview = columnPreView.ActualWidth;
    double widthSplitter = columnSplitter.ActualWidth;
    double widthListView = columnListView.ActualWidth;
    if (widthListView <= lastListViewWidth)
    {
        lastListViewWidth = Math.Min(lastListViewWidth, grid.ActualWidth * .85);
        lastListViewWidth = Math.Max(lastListViewWidth, grid.ActualWidth * .15);
        columnPreView.Width = new GridLength(grid.ActualWidth - lastListViewWidth - widthSplitter, GridUnitType.Star);
        columnListView.Width = new GridLength(lastListViewWidth, GridUnitType.Star);
    };
}

then it works as expected (with grid defined as the name of the Grid in XAML).

Cleocleobulus answered 8/11, 2022 at 10:47 Comment(0)
A
0

An alternative to adjusting the widths of the adjacent columns:

public class MovableSplitter : GridSplitter
{
    private PresentationSource Source;
    private KeyboardDevice KBDevice;

    //Colloect required information for the OnKeyDown method
    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        Source = PresentationSource.FromDependencyObject(this);
        KBDevice = Keyboard.PrimaryDevice;
    }

    //Move the splitter, positive values are down or right
    public void MoveSplitter(double change)
    {
        //Save the keyboard increment for restoration
        double oldIncrement = KeyboardIncrement;
        try
        {
            KeyboardIncrement = Math.Abs(change);
            //Is the grid adjust row heghts or column widths
            if (ResizeDirection == GridResizeDirection.Rows)
            {
                OnKeyDown(new KeyEventArgs(KBDevice, Source, 0, change > 0 ? Key.Down : Key.Up));
            }
            else
            {
                OnKeyDown(new KeyEventArgs(KBDevice, Source, 0, change > 0 ? Key.Right : Key.Left));
            }
        }
        catch { }
        //Restore the keyboard increment
        finally { KeyboardIncrement = oldIncrement; }
    }
}

For my use I was adjusting the splitter in the window size changed event. However, what I found was that the child controls ActualHeight and ActualWidth were not adjusted yet. I switched to the LayoutComplete event for the control.

If you do that keep in mind that adjusting the GridSplitter will set off another round of layout adjustments. Just something to watch for, some adjustment algorithms may result in an infinite loop of adjustments.

Antifouling answered 19/8 at 15:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.