自定义控件在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>
后来,我执行了项目,序列处理如下。
- 自定义窗口已创建。 (构造函数调用)
- 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值没有设置。
我应该怎么做才能解决这个问题?
希望得到您的帮助。
感谢您的阅读。
谢谢指教,我解决了这个问题
我修改了 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">
如果你有更好的方法,请告诉我。
谢谢指教。
我的英语水平很差,因为我的母语不是英语。 希望大家理解。
我创建了一个覆盖标题栏形状的自定义 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>
后来,我执行了项目,序列处理如下。
- 自定义窗口已创建。 (构造函数调用)
- 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值没有设置。
我应该怎么做才能解决这个问题? 希望得到您的帮助。
感谢您的阅读。
谢谢指教,我解决了这个问题
我修改了 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">
如果你有更好的方法,请告诉我。
谢谢指教。