Skip to content

Commit 18ce2b8

Browse files
Add support for setting content in place of the title in a TitleBar (#1030)
* Add support for setting content in place of the title in a TitleBar * Use Header instead of HeaderLeft and TrailingContent instead of HeaderRight Refactor TitleBar properties for clarity and usability Renamed properties in the `TitleBar` class from `HeaderLeft` and `HeaderRight` to `Header` and `TrailingContent`. Updated XAML and C# files to reflect these changes, streamlining the structure of the `TitleBar`. Modified the constructor to set the `_titleBlock` to the new `Header` property. Adjusted hit testing logic in `WM.NCHITTEST` to accommodate the new property names, ensuring proper mouse interaction handling. These changes improve the overall clarity and usability of the `TitleBar` component. --------- Co-authored-by: pomian <[email protected]>
1 parent 0fc9208 commit 18ce2b8

File tree

3 files changed

+114
-17
lines changed

3 files changed

+114
-17
lines changed

src/Wpf.Ui.Gallery/Views/Windows/SandboxWindow.xaml

+59
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,65 @@
3030
<ui:TitleBar.Icon>
3131
<ui:ImageIcon Source="pack://application:,,,/Assets/wpfui.png" />
3232
</ui:TitleBar.Icon>
33+
<ui:TitleBar.Header>
34+
<Menu>
35+
<MenuItem Header="File">
36+
<MenuItem
37+
Header="New" />
38+
<MenuItem
39+
Header="New window" />
40+
<MenuItem
41+
Header="Open..." />
42+
<MenuItem
43+
Header="Save" />
44+
<MenuItem
45+
Header="Save As..." />
46+
<Separator />
47+
<MenuItem
48+
Header="Exit" />
49+
</MenuItem>
50+
<ui:MenuItem Header="Debug">
51+
<MenuItem
52+
Header="Undo" />
53+
<Separator />
54+
<MenuItem
55+
Header="Cut" />
56+
<MenuItem
57+
Header="Copy" />
58+
<MenuItem
59+
Header="Paste" />
60+
<MenuItem
61+
Header="Delete"
62+
IsEnabled="False" />
63+
<Separator />
64+
<MenuItem
65+
Header="Search with browser" />
66+
<MenuItem
67+
Header="Find..." />
68+
<MenuItem
69+
Header="Find next" />
70+
<Separator />
71+
<MenuItem
72+
Header="Select All" />
73+
</ui:MenuItem>
74+
</Menu>
75+
</ui:TitleBar.Header>
76+
<ui:TitleBar.TrailingContent>
77+
<Menu>
78+
<ui:MenuItem
79+
Foreground="{DynamicResource PaletteDeepOrangeBrush}"
80+
Icon="{ui:SymbolIcon Fire24, True}" />
81+
<ui:MenuItem
82+
Foreground="{DynamicResource PaletteGreenBrush}"
83+
Icon="{ui:SymbolIcon Play24}" />
84+
<ui:MenuItem
85+
Foreground="{DynamicResource PaletteRedBrush}"
86+
Icon="{ui:SymbolIcon Stop24}" />
87+
<ui:MenuItem
88+
Foreground="{DynamicResource PaletteLightBlueBrush}"
89+
Icon="{ui:SymbolIcon ArrowClockwise24}" />
90+
</Menu>
91+
</ui:TitleBar.TrailingContent>
3392
</ui:TitleBar>
3493

3594
<StackPanel Margin="24">

src/Wpf.Ui/Controls/TitleBar/TitleBar.cs

+44-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// All Rights Reserved.
55

66
using System.Diagnostics;
7+
using System.Windows.Data;
78
using System.Windows.Input;
89
using Wpf.Ui.Designer;
910
using Wpf.Ui.Input;
@@ -52,13 +53,25 @@ public class TitleBar : System.Windows.Controls.Control, IThemeControl
5253
new PropertyMetadata(null)
5354
);
5455

55-
/// <summary>Identifies the <see cref="Header"/> dependency property.</summary>
56+
/// <summary>
57+
/// Property for <see cref="Header"/>.
58+
/// </summary>
5659
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
5760
nameof(Header),
5861
typeof(object),
5962
typeof(TitleBar),
6063
new PropertyMetadata(null)
6164
);
65+
66+
/// <summary>
67+
/// Property for <see cref="TrailingContent"/>.
68+
/// </summary>
69+
public static readonly DependencyProperty TrailingContentProperty = DependencyProperty.Register(
70+
nameof(TrailingContent),
71+
typeof(object),
72+
typeof(TitleBar),
73+
new PropertyMetadata(null)
74+
);
6275

6376
/// <summary>Identifies the <see cref="ButtonsForeground"/> dependency property.</summary>
6477
public static readonly DependencyProperty ButtonsForegroundProperty = DependencyProperty.Register(
@@ -209,13 +222,22 @@ public string? Title
209222
}
210223

211224
/// <summary>
212-
/// Gets or sets the content displayed in the <see cref="TitleBar"/>.
225+
/// Gets or sets the content displayed in the left side of the <see cref="TitleBar"/>.
213226
/// </summary>
214-
public object? Header
227+
public object Header
215228
{
216229
get => GetValue(HeaderProperty);
217230
set => SetValue(HeaderProperty, value);
218231
}
232+
233+
/// <summary>
234+
/// Gets or sets the content displayed in right side of the <see cref="TitleBar"/>.
235+
/// </summary>
236+
public object TrailingContent
237+
{
238+
get => GetValue(TrailingContentProperty);
239+
set => SetValue(TrailingContentProperty, value);
240+
}
219241

220242
/// <summary>
221243
/// Gets or sets the foreground of the navigation buttons.
@@ -376,6 +398,7 @@ public event TypedEventHandler<TitleBar, RoutedEventArgs> HelpClicked
376398

377399
/*private System.Windows.Controls.Grid _mainGrid = null!;*/
378400
private System.Windows.Controls.ContentPresenter _icon = null!;
401+
private readonly TextBlock _titleBlock;
379402

380403
/// <summary>
381404
/// Initializes a new instance of the <see cref="TitleBar"/> class and sets the default <see cref="FrameworkElement.Loaded"/> event.
@@ -386,6 +409,12 @@ public TitleBar()
386409

387410
dpiScale ??= VisualTreeHelper.GetDpi(this);
388411

412+
_titleBlock = new TextBlock();
413+
_titleBlock.VerticalAlignment = VerticalAlignment.Center;
414+
_titleBlock.SetBinding(System.Windows.Controls.TextBlock.TextProperty, new Binding(nameof(Title)) { Source = this });
415+
_titleBlock.SetBinding(System.Windows.Controls.TextBlock.FontSizeProperty, new Binding(nameof(FontSize)) { Source = this });
416+
Header = _titleBlock;
417+
389418
Loaded += OnLoaded;
390419
Unloaded += OnUnloaded;
391420
}
@@ -617,9 +646,19 @@ or User32.WM.NCLBUTTONUP
617646

618647
bool isMouseOverHeaderContent = false;
619648

620-
if (message == User32.WM.NCHITTEST && Header is UIElement headerUiElement)
649+
if (message == User32.WM.NCHITTEST && (TrailingContent is UIElement || Header is UIElement))
621650
{
622-
isMouseOverHeaderContent = headerUiElement.IsMouseOverElement(lParam);
651+
UIElement? headerLeftUIElement = Header as UIElement;
652+
UIElement? headerRightUiElement = TrailingContent as UIElement;
653+
654+
if (headerLeftUIElement is not null && headerLeftUIElement != _titleBlock)
655+
{
656+
isMouseOverHeaderContent = headerLeftUIElement.IsMouseOverElement(lParam) || (headerRightUiElement?.IsMouseOverElement(lParam) ?? false);
657+
}
658+
else
659+
{
660+
isMouseOverHeaderContent = headerRightUiElement?.IsMouseOverElement(lParam) ?? false;
661+
}
623662
}
624663

625664
switch (message)

src/Wpf.Ui/Controls/TitleBar/TitleBar.xaml

+11-12
Original file line numberDiff line numberDiff line change
@@ -118,42 +118,41 @@
118118
VerticalAlignment="Center">
119119
<Grid.ColumnDefinitions>
120120
<ColumnDefinition Width="Auto" />
121-
<ColumnDefinition Width="Auto" />
122121
</Grid.ColumnDefinitions>
123122

124123
<!-- Custom application icon -->
125124
<ContentPresenter
126125
x:Name="PART_Icon"
127126
Grid.Column="0"
128127
Height="16"
129-
Margin="0,0,12,0"
130128
VerticalAlignment="Center"
131129
Content="{TemplateBinding Icon}"
132130
Focusable="False"
133131
RenderOptions.BitmapScalingMode="HighQuality" />
134-
135-
<!-- Main application title -->
136-
<TextBlock
137-
Grid.Column="1"
138-
VerticalAlignment="Center"
139-
FontSize="{TemplateBinding FontSize}"
140-
Text="{TemplateBinding Title}" />
141132
</Grid>
133+
142134
<Grid Grid.Column="1">
143135
<Grid.ColumnDefinitions>
136+
<ColumnDefinition Width="Auto" />
144137
<ColumnDefinition Width="*" />
145138
<ColumnDefinition Width="Auto" />
146139
</Grid.ColumnDefinitions>
147140

148-
<!-- Additional header content -->
141+
<!-- Title text or other header content -->
149142
<ContentPresenter
150143
Grid.Column="0"
151-
HorizontalAlignment="Right"
144+
HorizontalAlignment="Left"
152145
Content="{TemplateBinding Header}" />
146+
147+
<!-- Additional header content -->
148+
<ContentPresenter
149+
Grid.Column="1"
150+
HorizontalAlignment="Right"
151+
Content="{TemplateBinding TrailingContent}" />
153152

154153
<!-- Navigation buttons - Close, Restore, Maximize, Minimize -->
155154
<Grid
156-
Grid.Column="1"
155+
Grid.Column="2"
157156
HorizontalAlignment="Right"
158157
VerticalAlignment="Top">
159158
<Grid.ColumnDefinitions>

0 commit comments

Comments
 (0)