0

我的英语水平很差,因为我不是以英语为母语的人。我希望你能理解。

我创建了一个覆盖标题栏形状的自定义窗口。部分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>

然后,我执行了该项目,并按如下方式处理了序列。

  1. 自定义窗口已创建。(构造函数调用)
  2. 设置了 CustomWindow 的 TitleBarHeight 值
  3. 调用 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的值也没有设置。

我应该怎么做才能解决这个问题?我希望能得到你的帮助。

感谢您的阅读。

4

1 回答 1

0

感谢您的建议,我解决了这个问题。

我修改了 xaml 代码,如下所示。

<Border x:Name="PART_TITLEBAR"
        Margin="2,0,2,2"
        Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:CustomWindow}, Path=TitleBarHeight}"
        DockPanel.Dock="Top"
        CornerRadius="2"
        Background="Transparent">

如果您有更好的方法,请告诉我。

谢谢你的建议。

于 2019-12-20T09:18:05.883 回答