fix(dock): implement group layout and selection binding fixes

This commit is contained in:
2026-03-28 13:05:35 +09:00
parent efc9e8862d
commit 038a13bbe0

View File

@@ -20,6 +20,25 @@ public sealed partial class DockLayout : Control
public DockLayout() public DockLayout()
{ {
DefaultStyleKey = typeof(DockLayout); DefaultStyleKey = typeof(DockLayout);
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
if (Root != null)
{
SubscribeToNode(Root);
}
RenderTree();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
if (Root != null)
{
UnsubscribeFromNode(Root);
}
} }
public DockGroupNode? Root public DockGroupNode? Root
@@ -40,7 +59,7 @@ public sealed partial class DockLayout : Control
layout.UnsubscribeFromNode(oldRoot); layout.UnsubscribeFromNode(oldRoot);
} }
if (e.NewValue is DockGroupNode newRoot) if (e.NewValue is DockGroupNode newRoot && layout.IsLoaded)
{ {
layout.SubscribeToNode(newRoot); layout.SubscribeToNode(newRoot);
} }
@@ -79,26 +98,43 @@ public sealed partial class DockLayout : Control
private void OnNodePropertyChanged(object? sender, PropertyChangedEventArgs e) private void OnNodePropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
// Re-render on relevant property changes (e.g. Orientation) // Filter to relevant property names
RenderTree(); if (e.PropertyName == nameof(DockGroupNode.Orientation) ||
e.PropertyName == nameof(DockPanelNode.SelectedIndex) ||
e.PropertyName == nameof(DockPanelNode.SelectedItem))
{
RenderTree();
}
} }
private void OnChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) private void OnChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{ {
// Handle subscriptions for new/removed children if (e.Action == NotifyCollectionChangedAction.Reset)
if (e.OldItems != null)
{ {
foreach (DockNode oldNode in e.OldItems) // On Reset, we don't know what was removed.
// Simplest is to unsubscribe from everything and resubscribe from Root.
if (Root != null)
{ {
UnsubscribeFromNode(oldNode); UnsubscribeFromNode(Root);
SubscribeToNode(Root);
} }
} }
else
if (e.NewItems != null)
{ {
foreach (DockNode newNode in e.NewItems) if (e.OldItems != null)
{ {
SubscribeToNode(newNode); foreach (DockNode oldNode in e.OldItems)
{
UnsubscribeFromNode(oldNode);
}
}
if (e.NewItems != null)
{
foreach (DockNode newNode in e.NewItems)
{
SubscribeToNode(newNode);
}
} }
} }
@@ -122,11 +158,30 @@ public sealed partial class DockLayout : Control
{ {
if (node is DockGroupNode groupNode) if (node is DockGroupNode groupNode)
{ {
// Simple visualizer for now, full grid logic in next step
var grid = new Grid(); var grid = new Grid();
foreach (var child in groupNode.Children) var children = groupNode.Children;
for (int i = 0; i < children.Count; i++)
{ {
grid.Children.Add(CreateUIForNode(child)); if (groupNode.Orientation == Orientation.Horizontal)
{
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
}
else
{
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
}
var childUI = CreateUIForNode(children[i]);
if (groupNode.Orientation == Orientation.Horizontal)
{
Grid.SetColumn(childUI as FrameworkElement, i);
}
else
{
Grid.SetRow(childUI as FrameworkElement, i);
}
grid.Children.Add(childUI);
} }
return grid; return grid;
} }
@@ -139,15 +194,15 @@ public sealed partial class DockLayout : Control
VerticalAlignment = VerticalAlignment.Stretch VerticalAlignment = VerticalAlignment.Stretch
}; };
// Bind selection state // Bind selection state using TabView DPs
tabView.SetBinding(Selector.SelectedIndexProperty, new Binding tabView.SetBinding(TabView.SelectedIndexProperty, new Binding
{ {
Source = panelNode, Source = panelNode,
Path = new PropertyPath(nameof(DockPanelNode.SelectedIndex)), Path = new PropertyPath(nameof(DockPanelNode.SelectedIndex)),
Mode = BindingMode.TwoWay Mode = BindingMode.TwoWay
}); });
tabView.SetBinding(Selector.SelectedItemProperty, new Binding tabView.SetBinding(TabView.SelectedItemProperty, new Binding
{ {
Source = panelNode, Source = panelNode,
Path = new PropertyPath(nameof(DockPanelNode.SelectedItem)), Path = new PropertyPath(nameof(DockPanelNode.SelectedItem)),