Skip to content

Commit ca7524e

Browse files
authored
Merge pull request #283 from tedd/forge-content-alignment-10780616145795732953
🏗️ Forge: Control Content Alignment Parity Integration
2 parents 58e6fb1 + 6770367 commit ca7524e

6 files changed

Lines changed: 64 additions & 0 deletions

File tree

.jules/forge.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@
130130
## 2026-03-09 - ScrollViewer ScrollBarVisibility Attached Properties
131131
**Observation:** Discovered a parity deficit where `ScrollViewer.HorizontalScrollBarVisibility` and `VerticalScrollBarVisibility` were implemented as standard C# properties rather than dependency properties, and specifically, they were not attached properties. This violates WPF architecture where scroll bar visibility is a canonical attached property used widely in templates and styles on elements containing a ScrollViewer (such as ListBox).
132132
**Strategic Action:** Refactored `HorizontalScrollBarVisibility` and `VerticalScrollBarVisibility` to be registered via `DependencyProperty.RegisterAttached`, implementing the required static `Get...` and `Set...` methods while maintaining instance property wrappers, bringing it into strict 1:1 behavioral and structural mapping with WPF standard API.
133+
134+
## 2026-03-09 - Control Content Alignment Parity Integration
135+
**Observation:** Discovered a parity deficit where the `Control` class lacked `HorizontalContentAlignment` and `VerticalContentAlignment` dependency properties. Consequently, components utilizing control templates and `ContentPresenter` (like `ContentControl`, `Button`, `GroupBox`, `Expander`) could not leverage declarative bindings to adjust the internal alignment of their content, restricting standard WPF layout paradigms.
136+
**Strategic Action:**
137+
- Registered `HorizontalContentAlignment` and `VerticalContentAlignment` dependency properties on the `Control` base class.
138+
- Modified default `ControlTemplate` implementations within `ContentControl`, `Button`, `GroupBox`, and `Expander` to bind the generated `ContentPresenter`'s `HorizontalAlignment` and `VerticalAlignment` directly to these new inherited parent properties, bridging a significant component styling parity gap.
133139
## 2026-03-09 - DataContext Propagation Parity Integration
134140
**Observation:** Discovered a core architectural deficit where layout container controls (e.g., `Border`, `DialogBox`, `Table`, `TuiWindow`, `Grid`) were manually overriding `OnDataContextChanged` to explicitly assign a local `DataContext` value onto their content or child elements. This manual set operation inadvertently overwrote and masked standard logical/visual tree inheritance tracking, breaking WPF/XAML isomorphism by treating inherited context mutations as local overrides.
135141
**Strategic Action:**

src/Tedd.TUI/Button.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ public Button()
6161
contentTemplateBinding.RelativeSource = RelativeSource.TemplatedParent;
6262
cp.SetBinding(ContentPresenter.ContentTemplateProperty, contentTemplateBinding);
6363

64+
// Bind HorizontalAlignment to parent.HorizontalContentAlignment
65+
var hAlignBinding = new Binding("HorizontalContentAlignment");
66+
hAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
67+
cp.SetBinding(UIElement.HorizontalAlignmentProperty, hAlignBinding);
68+
69+
// Bind VerticalAlignment to parent.VerticalContentAlignment
70+
var vAlignBinding = new Binding("VerticalContentAlignment");
71+
vAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
72+
cp.SetBinding(UIElement.VerticalAlignmentProperty, vAlignBinding);
73+
6474
border.Content = cp;
6575
return border;
6676
});

src/Tedd.TUI/ContentControl.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ public ContentControl()
4040
templateBinding.RelativeSource = RelativeSource.TemplatedParent;
4141
cp.SetBinding(ContentPresenter.ContentTemplateProperty, templateBinding);
4242

43+
// Bind HorizontalAlignment to parent.HorizontalContentAlignment
44+
var hAlignBinding = new Binding("HorizontalContentAlignment");
45+
hAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
46+
cp.SetBinding(UIElement.HorizontalAlignmentProperty, hAlignBinding);
47+
48+
// Bind VerticalAlignment to parent.VerticalContentAlignment
49+
var vAlignBinding = new Binding("VerticalContentAlignment");
50+
vAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
51+
cp.SetBinding(UIElement.VerticalAlignmentProperty, vAlignBinding);
52+
4353
return cp;
4454
});
4555
}

src/Tedd.TUI/Control.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@ public Thickness BorderThickness
4242
set => SetValue(BorderThicknessProperty, value);
4343
}
4444

45+
public static readonly DependencyProperty HorizontalContentAlignmentProperty =
46+
DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(Control), HorizontalAlignment.Stretch);
47+
48+
public HorizontalAlignment HorizontalContentAlignment
49+
{
50+
get => (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty);
51+
set => SetValue(HorizontalContentAlignmentProperty, value);
52+
}
53+
54+
public static readonly DependencyProperty VerticalContentAlignmentProperty =
55+
DependencyProperty.Register("VerticalContentAlignment", typeof(VerticalAlignment), typeof(Control), VerticalAlignment.Stretch);
56+
57+
public VerticalAlignment VerticalContentAlignment
58+
{
59+
get => (VerticalAlignment)GetValue(VerticalContentAlignmentProperty);
60+
set => SetValue(VerticalContentAlignmentProperty, value);
61+
}
62+
4563
// Tracks, per DependencyObject, which dependency properties currently have values applied by active triggers
4664
private System.Collections.Generic.Dictionary<DependencyObject, System.Collections.Generic.HashSet<DependencyProperty>>? _activeTriggerProperties;
4765

src/Tedd.TUI/Expander.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ public Expander()
7979
var contentTemplateBinding = new Binding("ContentTemplate") { RelativeSource = RelativeSource.TemplatedParent };
8080
contentPresenter.SetBinding(ContentPresenter.ContentTemplateProperty, contentTemplateBinding);
8181

82+
// Bind HorizontalAlignment to parent.HorizontalContentAlignment
83+
var hAlignBinding = new Binding("HorizontalContentAlignment");
84+
hAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
85+
contentPresenter.SetBinding(UIElement.HorizontalAlignmentProperty, hAlignBinding);
86+
87+
// Bind VerticalAlignment to parent.VerticalContentAlignment
88+
var vAlignBinding = new Binding("VerticalContentAlignment");
89+
vAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
90+
contentPresenter.SetBinding(UIElement.VerticalAlignmentProperty, vAlignBinding);
91+
8292
contentPresenter.Visibility = expander.IsExpanded;
8393

8494
stack.Children.Add(contentPresenter);

src/Tedd.TUI/GroupBox.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ public GroupBox()
6363
contentTemplateBinding.RelativeSource = RelativeSource.TemplatedParent;
6464
cp.SetBinding(ContentPresenter.ContentTemplateProperty, contentTemplateBinding);
6565

66+
// Bind HorizontalAlignment to parent.HorizontalContentAlignment
67+
var hAlignBinding = new Binding("HorizontalContentAlignment");
68+
hAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
69+
cp.SetBinding(UIElement.HorizontalAlignmentProperty, hAlignBinding);
70+
71+
// Bind VerticalAlignment to parent.VerticalContentAlignment
72+
var vAlignBinding = new Binding("VerticalContentAlignment");
73+
vAlignBinding.RelativeSource = RelativeSource.TemplatedParent;
74+
cp.SetBinding(UIElement.VerticalAlignmentProperty, vAlignBinding);
75+
6676
border.Content = cp;
6777

6878
var titleCp = new ContentPresenter();

0 commit comments

Comments
 (0)