Поведение WPF GridSplitter при изменении размера родительского окна

Я определил свой XAML GridSplittler следующим образом.

<Window>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
    </Grid>

    <Border Grid.Column="0" Background="Red" />
    <GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="3" Height="Auto" HorizontalAlighment="Stretch" VerticalAlignment="Stretch" />
    <Border Grid.Column="0" Background="Green" />

</Window>

Это создаст два столбца с разделителем сетки между ними, и он будет правильно изменять размер столбцов, так как разделитель сетки перетаскивается влево и вправо. Теперь, если вы измените размер всего окна, я бы хотел, чтобы ширина левого красного столбца оставалась неизменной, а ширина правого зеленого столбца изменялась (по мере изменения размера окна). Это тот же эффект, что и при изменении размера всего приложения Visual Studio, когда ширина Solution Explorer остается фиксированной, но ширина вкладки кода изменяется. Также как и SQL Server Management Studio; ширина Object Explorer остается фиксированной, но ширина вкладок SQL изменяется. Я понимаю, что в этих двух примерах используется более сложный элемент управления стыковкой, но я надеялся достичь того же результата с помощью WPF GridSplitter.

Изменить: на основе предложений mathieu все, что было необходимо, это дать начальному определению ширины первого столбца (показано с использованием 200 ниже).

<Grid Name="GridName">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Border Grid.Column="0" Background="Red" />
    <GridSplitter Name="SplitterName" Grid.Column="1" ResizeDirection="Columns" Width="3" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    <Border Grid.Column="2" Background="Green" />
</Grid>

Теперь, когда окно изменено в размере, оно только меняет ширину зеленой границы, а ширина красной границы остается неизменной. Спасибо!

1 ответ

Решение

Если вы не возражаете против некоторого кода позади, вы можете добиться такого поведения, реагируя на событие DragDelta разделителя и регулируя ширину первого столбца, удаляя ширину звезды и устанавливая ширину в соответствии с дельтой перетаскивания.

Xaml:

<Grid Name="GridName">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Border Grid.Column="0" Background="Red" />
    <GridSplitter Name="SplitterName" Grid.Column="1" ResizeDirection="Columns" Width="3" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
    <Border Grid.Column="2" Background="Green" />
</Grid>

Код позади

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        SplitterName.DragDelta += SplitterNameDragDelta;
    }

    private void SplitterNameDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        GridName.ColumnDefinitions[0].Width = new GridLength(GridName.ColumnDefinitions[0].ActualWidth + e.HorizontalChange);
    }
}

Я использовал снайпер Матье - и модифицировал его для использования кода. В моем случае мне нужно динамическое количество элементов, размер которых изменяет GridSplitter.

Я использовал Thumb Control, чтобы полностью контролировать действие

private Thumb GetNewThumbAsGridSplitter(int column)
    {
        var gs = new Thumb();
        gs.SetValue(Grid.ColumnProperty, column);
        // gs.SetValue(Grid.RowSpanProperty, 2);
        // gs.SetValue(Grid.RowProperty, 1);
        gs.Width = 5;
        gs.MouseEnter += (o, i) =>
        {
            Mouse.OverrideCursor = Cursors.ScrollWE;
        };
        gs.MouseLeave += (o, i) =>
        {
            Mouse.OverrideCursor = Cursors.Arrow;
        };
        gs.DragDelta += (o, i) =>
        {
            var grid = (Grid)gs.Parent;
            var previous = (YourControl)((grid.Children[column - 1]));
            var next = (YourControl)(grid.Children[column + 1]);

            if (next.MinWidth >= (next.ActualWidth - i.HorizontalChange))
            {
                return;
            }

            if (previous.MinWidth >= (previous.ActualWidth + i.HorizontalChange))
            {
                return;
            }

            previous.Width = previous.ActualWidth + i.HorizontalChange;
            next.Width = next.ActualWidth - i.HorizontalChange;
        };

        return gs;
    }
Другие вопросы по тегам