◆ 気持ちよく分割できる

この記事書いたときに作ったもの
<Window x:Class="wpf_testproj.Window00"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:wpf_testproj"
        mc:Ignorable="d"
        Title="Window00" Height="600" Width="600"
        PreviewKeyDown="Window_PreviewKeyDown">
    <Grid x:Name="root_grid">
        <Grid>
            <TextBox />
        </Grid>
    </Grid>
</Window>
public partial class Window00 : Window
{
    public Window00()
    {
        InitializeComponent();
    }

    private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        var focused = FocusManager.GetFocusedElement(this) as TextBox;
        if (focused == null) return;

        var grid = focused.Parent as Grid;

        // Ctrl-F2
        if (e.Key == Key.F2 && Keyboard.Modifiers == ModifierKeys.Control)
        {
            var new_grid = this.splitVertical(grid);

            // focus created textbox
            new_grid.Children[0].Focus();
        }
        // Shift-F2
        else if (e.Key == Key.F2 && Keyboard.Modifiers == ModifierKeys.Shift)
        {
            var new_grid = this.splitHorizontal(grid);

            // focus created textbox
            new_grid.Children[0].Focus();
        }
        // Ctrl-F6
        else if (e.Key == Key.F6 && Keyboard.Modifiers == ModifierKeys.Control)
        {
            var sibling = this.destroy(grid);

            // focus textbox in left sibling
            this.find<TextBox>(sibling)?.Focus();
        }
        else
        {
            return;
        }
        e.Handled = true;
    }

    /// <summary>
    /// 横に追加する
    /// </summary>
    /// <param name="grid"></param>
    /// <returns></returns>

    private Grid splitVertical(Grid grid)
    {
        var new_grid = new Grid();

        new_grid.SetValue(Grid.RowProperty, grid.GetValue(Grid.RowProperty));
        new_grid.SetValue(Grid.ColumnProperty, grid.GetValue(Grid.ColumnProperty));

        new_grid.ColumnDefinitions.Add(new ColumnDefinition { MinWidth = 5 });
        new_grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        new_grid.ColumnDefinitions.Add(new ColumnDefinition { MinWidth = 5 });

        var parent = grid.Parent as Grid;
        parent.Children.Remove(grid);
        parent.Children.Add(new_grid);

        var left = grid;
        left.ClearValue(Grid.RowProperty);
        left.SetValue(Grid.ColumnProperty, 0);
        new_grid.Children.Add(left);

        var right = this.generate();
        right.SetValue(Grid.ColumnProperty, 2);
        new_grid.Children.Add(right);

        var splitter = new GridSplitter
        {
            Width = 1,
            Background = new SolidColorBrush(Colors.Gray),
            HorizontalAlignment = HorizontalAlignment.Stretch,
        };
        splitter.SetValue(Grid.ColumnProperty, 1);
        new_grid.Children.Add(splitter);

        return right;
    }

    /// <summary>
    /// 縦に追加する
    /// </summary>
    /// <param name="grid"></param>
    /// <returns></returns>

    private Grid splitHorizontal(Grid grid)
    {
        var new_grid = new Grid();

        new_grid.SetValue(Grid.RowProperty, grid.GetValue(Grid.RowProperty));
        new_grid.SetValue(Grid.ColumnProperty, grid.GetValue(Grid.ColumnProperty));

        new_grid.RowDefinitions.Add(new RowDefinition { MinHeight = 5 });
        new_grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
        new_grid.RowDefinitions.Add(new RowDefinition { MinHeight = 5 });

        var parent = grid.Parent as Grid;
        parent.Children.Remove(grid);
        parent.Children.Add(new_grid);

        var top = grid;
        top.ClearValue(Grid.ColumnProperty);
        top.SetValue(Grid.RowProperty, 0);
        new_grid.Children.Add(top);

        var bottom = this.generate();
        bottom.SetValue(Grid.RowProperty, 2);
        new_grid.Children.Add(bottom);

        var splitter = new GridSplitter
        {
            Height = 1,
            Background = new SolidColorBrush(Colors.Gray),
            HorizontalAlignment = HorizontalAlignment.Stretch
        };
        splitter.SetValue(Grid.RowProperty, 1);
        new_grid.Children.Add(splitter);

        return bottom;
    }

    /// <summary>
    /// 削除
    /// </summary>
    /// <param name="grid"></param>
    /// <returns></returns>

    private Grid destroy(Grid grid)
    {
        var parent = grid.Parent as Grid;
        if (parent == this.root_grid) return null;

        var sibling = (Grid)parent.Children.Cast<UIElement>().First(e => e is Grid && e != grid);
        sibling.SetValue(Grid.RowProperty, parent.GetValue(Grid.RowProperty));
        sibling.SetValue(Grid.ColumnProperty, parent.GetValue(Grid.ColumnProperty));

        var grandparent = parent.Parent as Grid;
        parent.Children.Clear();
        grandparent.Children.Remove(parent);
        grandparent.Children.Add(sibling);

        return sibling;
    }

    private Grid generate()
    {
        return new Grid
        {
            Children = { new TextBox() }
        };
    }

    private T closest<T>(FrameworkElement elem)
        where T : FrameworkElement
    {
        if (elem == null) return null;
        if (elem is T t) return t;
        return this.closest<T>(elem.Parent as FrameworkElement);
    }

    private T find<T>(Grid grid)
        where T : FrameworkElement
    {
        foreach (UIElement i in grid.Children)
        {
            if (i is T t) return t;
            if (i is Grid g)
            {
                var r = this.find<T>(g);
                if (r != null) return r;
            }
        }
        return null;
    }
}

Gist

Ctrl-F2 で縦に分割
Shift-F2 で横に分割
Ctrl-F6 で選択中を削除

これだけですが どこかで使いまわせそうです

gridiv

構造

分割するごとに Grid がネストします
Grid
  Grid             *
  Separator
  Grid
    Grid
      Grid         *
      Separator
      Grid         *
    Separator
    Grid           *

* の Grid が中身(ここでは TextBox) があるものです

ひとつのグリッドに Grid 3 つと Separator 2 つのようにまとめるのもありだったのですが
縦横分割がある都合上 縦分割の後に横分割してさらに縦分割などあるので ネストしていかないとできない部分もあります
連続して同じ方向に分割したときだけまとめることもできますが 処理が複雑になるのでシンプルな 2 分割の繰り返しにしてます

Binding はなし

問題があるとすれば View だけでやってるところ
Binding はしていません

なので TextBox を Binding して処理したいときには扱いづらいです

かといっても Binding するには WPF がデータ側をメインに扱う作りなので Binding ソースのデータ側を準備して それに対応する View のテンプレートを作る ということになるので分割の制御が大変になります

それにネストしてるのは見た目の都合なのにデータ側もネスト構造にするのは抵抗あります