自定义控件在xaml中使用时如何设置DP值? (声明时)

How to set DP value when the custom control use in the xaml? (when declaring)

我的英语水平很差,因为我的母语不是英语。 希望大家理解。

我创建了一个覆盖标题栏形状的自定义 window。 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值没有设置。

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

感谢您的阅读。

谢谢指教,我解决了这个问题

我修改了 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">

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

谢谢指教。