我的英语水平很差,因为我不是以英语为母语的人。我希望你能理解。
我创建了一个覆盖标题栏形状的自定义窗口。部分xaml代码如下图所示。
<Style x:Key="MainWindow" TargetType="{x:Type Window}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<Border x:Name="PART_TITLEBAR"
Margin="2,0,2,2"
Height="30"
DockPanel.Dock="Top"
CornerRadius="2"
Background="Transparent">
除了一个问题外,此控件运行良好。问题是不能设置DP的值。控件的部分cs代码如下图所示。
[TemplatePart(Name = "PART_TITLEBAR", Type = typeof(UIElement))]
public partial class CustomWindow : Window
{
private UIElement TitleBar { get; set; }
#region Dependency Properties for appearance.
public int TitleBarHeight
{
get { return (int)GetValue(TitleBarHeightProperty); }
set { SetValue(TitleBarHeightProperty, value); }
}
// Using a DependencyProperty as the backing store for TitleBarHeight. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleBarHeightProperty =
DependencyProperty.Register("TitleBarHeight", typeof(int), typeof(CustomWindow), new PropertyMetadata(TitleBarHeightChanged));
public static void TitleBarHeightChanged(DependencyObject dp, DependencyPropertyChangedEventArgs args)
{
CustomWindow window = dp as CustomWindow;
Border titleBar = window.TitleBar as Border;
if (titleBar == null) return;
titleBar.Height = (int)args.NewValue;
}
public SolidColorBrush TitleTextBrush
{
get { return (SolidColorBrush)GetValue(TitleTextBrushProperty); }
set { SetValue(TitleTextBrushProperty, value); }
}
// Using a DependencyProperty as the backing store for TitleTextBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleTextBrushProperty =
DependencyProperty.Register("TitleTextBrush", typeof(SolidColorBrush), typeof(CustomWindow), new PropertyMetadata(TitleTextBrushChanged));
public static void TitleTextBrushChanged(DependencyObject dp, DependencyPropertyChangedEventArgs args)
{
CustomWindow window = dp as CustomWindow;
Border titleBar = window.TitleBar as Border;
if (titleBar == null) return;
// find the textblock control of the children of the titlebar and change the value of the foreground of the control.
}
#endregion
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
AttachToVisualTree();
}
private void AttachToVisualTree()
{
AttachCloseButton();
AttachMinimizeButton();
AttachMaximizeRestoreButton();
AttachTitleBar();
AttachBorders();
}
private void AttachTitleBar()
{
if (TitleBar != null)
{
TitleBar.RemoveHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnTitlebarClick));
}
UIElement titleBar = GetChildControl<UIElement>("PART_TITLEBAR");
if (titleBar != null)
{
TitleBar = titleBar;
titleBar.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnTitlebarClick));
}
}
我试图追踪问题并找到了原因。首先,我在主项目中加载了自定义控件,并在自定义控件上设置了 DP 的值,如下所示。
<custom:CustomWindow TitleBarHeight="20">
<.../>
</custom:CustomWindow>
然后,我执行了该项目,并按如下方式处理了序列。
- 自定义窗口已创建。(构造函数调用)
- 设置了 CustomWindow 的 TitleBarHeight 值
- 调用 CustomWindow 的 OnApplyTemplate()。
根据我的确认,序列 2 是问题的起点。
在序列 2 中,WPF 试图设置 CustomWindow 的 TitleBarHeight 值。因此调用下面的代码。
public static void TitleBarHeightChanged(DependencyObject dp, DependencyPropertyChangedEventArgs args)
{
CustomWindow window = dp as CustomWindow;
Border titleBar = window.TitleBar as Border;
if (titleBar == null) return;
titleBar.Height = (int)args.NewValue;
}
但是此时,TitleBar 还没有被实例化,所以 TitleBarHeight 值没有被设置。结果,它将被转移到下面的例程中。
if (titleBar == null) return;
之后,调用 OnApplyTemplate() 并实例化 TitleBar。
总结:执行<custom:CustomWindow TitleBarHeight="20">逻辑时,此时CustomWindow的TitleBar没有被实例化,所以TitleBarHeight的值也没有设置。
我应该怎么做才能解决这个问题?我希望能得到你的帮助。
感谢您的阅读。