Поведение 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;
}