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

问题描述 投票:0回答:1

我的英语能力很差,因为我不会说英语。希望您能理解。

我创建了一个覆盖标题栏形状的自定义窗口。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. 创建CustomWindow。 (称为构造函数)
  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。

摘要:当执行逻辑时,此时CustomWindow的TitleBar尚未实例化,因此未设置TitleBarHeight值。

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

感谢您阅读。

wpf custom-controls dependency-properties apply-templates
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">

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

谢谢您的建议。

© www.soinside.com 2019 - 2024. All rights reserved.