wpf: Можно ли использовать разделитель сетки вне сетки?

У меня есть StackPanel, и он идеально подходит для разметки столбцов, которые пользователь добавляет во время выполнения. Но я бы хотел, чтобы размеры столбцов изменялись, и я читал об элементе управления GridSplitter. Вот что мне интересно: является ли GridSplitter заменой wpf для сплиттера WinForms? Другими словами, это де-факто способ разрешить пользователям изменять размер областей окна? Это работает только внутри Grid? Если у меня есть элементы внутри стековой панели или стыковочной панели, могу ли я по-прежнему использовать разделитель сетки так же, как я использовал разделитель в WinForms? Если мне нужно использовать Grid, как я могу заставить его вести себя так же, как StackPanel? (надеюсь до этого не дойдет)


person Community    schedule 13.05.2009    source источник


Ответы (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 });
        }
    }
}
person Wallstreet Programmer    schedule 14.05.2009

GridSplitter работает только в сетке и является самым простым способом разрешить пользователям изменять размер элементов управления. Что вы имеете в виду, когда хотите, чтобы ваша сетка (с разделителями сетки) вела себя так же, как панель стека? Панель стека точно соответствует каждому из своих дочерних элементов, в то время как сетка с разделителями сетки оставляет это на усмотрение пользователя.

person Wallstreet Programmer    schedule 13.05.2009
comment
Привет, спасибо за ответ! В моем приложении пользователь может добавлять столбцы на родительскую панель во время выполнения. Я бы хотел, чтобы столбцы располагались слева, как поведение макета по умолчанию для панели стека. Но я также хотел бы изменить размер столбцов. Я стремлюсь к чему-то похожему на представление столбцов OSX Finder. - person ; 13.05.2009

Вот WPF SplitContainer с открытым исходным кодом: [http://wpfsplitcontainer.codeplex.com/]

person Community    schedule 11.08.2009