如何为无XAML的WPF Window子类实现TitleContent依赖属性?
WPF自定义带标题栏的Window子类解决方案
我有一个继承自WPF Window的SlimWindow类,目标是移除系统标题栏(WindowStyle=None),并给子类窗口提供可复用的自定义标题栏功能——通过自定义TitleContent依赖属性设置标题文本,子窗口的主体内容放在Window自带的Content中。但现有代码运行后窗口为空白黑色,无法显示标题和内容。
问题原因
- ContentSource使用错误:自定义的
TitleContent属性不能用ContentSource绑定,该属性仅适用于控件自带的[ContentProperty]标记属性。 - 主体Content未绑定:模板中的第二个
ContentPresenter未指定绑定到Window的Content属性,导致子窗口内容无法渲染。 - 未默认移除系统标题栏:基类未设置
WindowStyle=None,系统标题栏可能干扰自定义模板的显示。 - 缺少窗口交互支持:
WindowStyle=None后默认丢失拖动、调整大小功能,影响使用体验。
修正代码
1. 修正基类SlimWindow
在静态构造函数中添加WindowStyle的默认设置,确保系统标题栏被移除:
public class SlimWindow : Window { static SlimWindow() { // 指定默认样式Key DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimWindow), new FrameworkPropertyMetadata(typeof(SlimWindow))); // 默认移除系统标题栏 WindowStyleProperty.OverrideMetadata(typeof(SlimWindow), new FrameworkPropertyMetadata(WindowStyle.None)); } public object TitleContent { get => GetValue(TitleContentProperty); set => SetValue(TitleContentProperty, value); } public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register( nameof(TitleContent), typeof(object), typeof(SlimWindow)); }
2. 修正App.xaml中的控件模板
修复绑定错误并添加WindowChrome支持窗口交互:
<Application x:Class="WindowSubclassing.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WindowSubclassing" StartupUri="AWindow.xaml"> <Application.Resources> <Style TargetType="local:SlimWindow"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:SlimWindow}"> <Grid Background="Blue"> <!-- 添加WindowChrome实现窗口拖动、调整大小 --> <WindowChrome.WindowChrome> <WindowChrome CaptionHeight="30" ResizeBorderThickness="5" /> </WindowChrome.WindowChrome> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <!-- 绑定自定义TitleContent属性 --> <ContentPresenter Content="{TemplateBinding TitleContent}" Margin="10,5" VerticalAlignment="Center" Foreground="White"/> <!-- 加白色前景确保文本可见 --> <AdornerDecorator Grid.Row="1"> <!-- 绑定Window的Content属性,显示子窗口主体内容 --> <ContentPresenter Content="{TemplateBinding Content}"/> </AdornerDecorator> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Application.Resources> </Application>
3. 子窗口AWindow保持原有代码不变
<local:SlimWindow x:Class="WindowSubclassing.AWindow" 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:WindowSubclassing" mc:Ignorable="d" Height="450" Width="800" TitleContent="A Child Title"> <Grid> <TextBlock Text="A WINDOW" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/> </Grid> </local:SlimWindow>
效果说明
修正后启动AWindow,会看到蓝色背景的窗口:
- 顶部显示白色的"A Child Title"文本,支持窗口拖动(点击标题栏区域)
- 中间显示白色的"A WINDOW"文本
- 窗口边缘可拖动调整大小
内容的提问来源于stack exchange,提问作者Boppity Bop
相关产品推荐
相关产品推荐

