У меня есть StackPanel, и он идеально подходит для разметки столбцов, которые пользователь добавляет во время выполнения. Но я бы хотел, чтобы размеры столбцов изменялись, и я читал об элементе управления GridSplitter. Вот что мне интересно: является ли GridSplitter заменой wpf для сплиттера WinForms? Другими словами, это де-факто способ разрешить пользователям изменять размер областей окна? Это работает только внутри Grid? Если у меня есть элементы внутри стековой панели или стыковочной панели, могу ли я по-прежнему использовать разделитель сетки так же, как я использовал разделитель в WinForms? Если мне нужно использовать Grid, как я могу заставить его вести себя так же, как StackPanel? (надеюсь до этого не дойдет)
wpf: Можно ли использовать разделитель сетки вне сетки?
Ответы (3)
Ниже приведен пользовательский элемент управления, который позволяет добавлять элементы в виде столбцов. Между столбцами находятся разделители сетки. Пользователи могут нажать кнопку «Удалить», чтобы удалить добавленные столбцы, а столбцы можно добавить с помощью скрытого кода. Дайте мне знать, если это то, что вы искали.
Пользовательский элемент управления SmartGrid XAML:
<UserControl x:Class="SmartGridDemo.SmartGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Name="_grid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
</Grid>
</UserControl>
Код SmartGrid для управления пользователем:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace SmartGridDemo
{
public partial class SmartGrid : UserControl
{
public SmartGrid()
{
InitializeComponent();
}
public void Add(UIElement child)
{
int columnIndex = _grid.ColumnDefinitions.Count();
_grid.ColumnDefinitions.Add(
new ColumnDefinition()
{
Width = new GridLength(columnIndex == 0 ? 0 :5)
});
GridSplitter gridSplitter =
new GridSplitter()
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Stretch,
ResizeDirection = GridResizeDirection.Columns,
Background = Brushes.Black
};
_grid.Children.Add(gridSplitter);
Grid.SetColumn(gridSplitter, columnIndex);
Grid.SetRow(gridSplitter, 0);
Grid.SetRowSpan(gridSplitter, 2);
columnIndex++;
_grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
Button button = new Button();
button.Content = "Delete";
button.Tag = new TagTuple() {Child = child, GridSplitter = gridSplitter};
button.Click += new RoutedEventHandler(DeleteButton_Click);
_grid.Children.Add(button);
Grid.SetColumn(button, columnIndex);
Grid.SetRow(button, 0);
_grid.Children.Add(child);
Grid.SetColumn(child, columnIndex);
Grid.SetRow(child, 1);
}
private void DeleteButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
int columnIndex = Grid.GetColumn(button);
TagTuple tagTuple = button.Tag as TagTuple;
_grid.Children.Remove(tagTuple.GridSplitter);
_grid.Children.Remove(tagTuple.Child);
_grid.Children.Remove(button as UIElement);
_grid.ColumnDefinitions.RemoveAt(_grid.ColumnDefinitions.Count() - 1);
_grid.ColumnDefinitions.RemoveAt(_grid.ColumnDefinitions.Count() - 1);
foreach (UIElement child in _grid.Children)
{
int columnIndexForChild = Grid.GetColumn(child);
if (columnIndexForChild > columnIndex)
{
Grid.SetColumn(child, columnIndexForChild - 2);
}
}
}
private class TagTuple
{
public GridSplitter GridSplitter { get; set; }
public UIElement Child { get; set; }
}
}
}
Демонстрационный код, добавьте текст в TextBox и нажмите кнопку «Добавить», чтобы добавить новые столбцы, XAML:
<Window x:Class="SmartGridDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SmartGridDemo"
Title="SmartGridDemo" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox Name="_texBox" Grid.Row="0" Grid.Column="0" />
<Button Content="Add" Click="AddButton_Click" Grid.Row="0" Grid.Column="1" />
<local:SmartGrid x:Name="_smartGrid" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>
</Window>
Демо, за кодом:
using System;
using System.Windows;
using System.Windows.Controls;
namespace SmartGridDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
_smartGrid.Add(new TextBlock() { Text = "AAA" });
_smartGrid.Add(new TextBlock() { Text = "BBB" });
_smartGrid.Add(new TextBlock() { Text = "CCC" });
_smartGrid.Add(new TextBlock() { Text = "DDD" });
_smartGrid.Add(new TextBlock() { Text = "EEE" });
_smartGrid.Add(new TextBlock() { Text = "FFF" });
}
private void AddButton_Click(object sender, RoutedEventArgs e)
{
_smartGrid.Add(new TextBlock() { Text = _texBox.Text });
}
}
}
GridSplitter работает только в сетке и является самым простым способом разрешить пользователям изменять размер элементов управления. Что вы имеете в виду, когда хотите, чтобы ваша сетка (с разделителями сетки) вела себя так же, как панель стека? Панель стека точно соответствует каждому из своих дочерних элементов, в то время как сетка с разделителями сетки оставляет это на усмотрение пользователя.
Вот WPF SplitContainer с открытым исходным кодом: [http://wpfsplitcontainer.codeplex.com/]