WPF自定义控件:ViewBox上的HorizontalAlignment样式设置未正确初始化



我在.NET 5 WPF项目中有以下自定义控件:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SteelCloud.Controls"
xmlns:converters="clr-namespace:My.Controls.Converters">
<Style TargetType="{x:Type local:BorderedContainer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:BorderedContainer}">
<ControlTemplate.Resources>
<converters:BorderClipConverter x:Key="BorderClipConverter"/>
<converters:InnerBorderRadiusConverter x:Key="InnerBorderRadiusConverter"/>
<converters:HeaderRadiusConverter x:Key="HeaderRadiusConverter"/>
<converters:GridLengthConverter x:Key="GridLengthConverter"/>
</ControlTemplate.Resources>
<Border CornerRadius="{TemplateBinding BorderRadius}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Margin="{TemplateBinding Margin}"
Padding="{TemplateBinding Padding}">
<Border.Clip>
<MultiBinding Converter="{StaticResource BorderClipConverter}">
<Binding Path="ActualWidth"
RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight"
RelativeSource="{RelativeSource Self}" />
<Binding Path="CornerRadius"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.Clip>
<Border CornerRadius="{TemplateBinding BorderRadius, Converter={StaticResource InnerBorderRadiusConverter}}">
<Border.Clip>
<MultiBinding Converter="{StaticResource BorderClipConverter}">
<Binding Path="ActualWidth"
RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight"
RelativeSource="{RelativeSource Self}" />
<Binding Path="CornerRadius"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.Clip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border CornerRadius="{TemplateBinding BorderRadius, Converter={StaticResource HeaderRadiusConverter}}"
BorderBrush="{TemplateBinding BorderBrush}"
MaxHeight="{TemplateBinding HeaderSize}"
VerticalAlignment="Top"
Visibility="{TemplateBinding HeaderVisibility}">
<Border.Clip>
<MultiBinding Converter="{StaticResource BorderClipConverter}">
<Binding Path="ActualWidth"
RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight"
RelativeSource="{RelativeSource Self}" />
<Binding Path="CornerRadius"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.Clip>
<Grid VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="{TemplateBinding HeaderSize, Converter={StaticResource GridLengthConverter}}"/>
<RowDefinition Height="{TemplateBinding HeaderSeparatorSize}"/>
</Grid.RowDefinitions>
<Border Padding="{TemplateBinding HeaderMargin}"
Background="{TemplateBinding HeaderBackground}">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Viewbox HorizontalAlignment="{TemplateBinding HeaderHorizontalAlignment}">
<TextBlock Text="{TemplateBinding HeaderText}"
HorizontalAlignment="Left"/>
</Viewbox>
</Grid>
</Border>
<Rectangle Grid.Row="1"
Height="{TemplateBinding HeaderSeparatorSize}"
HorizontalAlignment="Stretch"
Fill="{TemplateBinding BorderBrush}"/>
</Grid>
</Border>
<ContentControl Grid.Row="1" 
Content="{TemplateBinding Content}"
VerticalAlignment="Stretch"/>
</Grid>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

具有以下定义:

public class BorderedContainer : ContentControl
{
static BorderedContainer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BorderedContainer), new FrameworkPropertyMetadata(typeof(BorderedContainer)));
}
public object Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
public new static readonly DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public CornerRadius BorderRadius
{
get => (CornerRadius) GetValue(BorderRadiusProperty);
set => SetValue(BorderRadiusProperty, value);
}
public static readonly DependencyProperty BorderRadiusProperty =
DependencyProperty.Register("BorderRadius", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public Brush HeaderBackground
{
get => (Brush) GetValue(HeaderBackgroundProperty);
set => SetValue(HeaderBackgroundProperty, value);
}
public static readonly DependencyProperty HeaderBackgroundProperty =
DependencyProperty.Register("HeaderBackground", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public GridLength HeaderSeparatorSize
{
get => (GridLength) GetValue(HeaderSeparatorSizeProperty);
set => SetValue(HeaderSeparatorSizeProperty, value);
}
public static readonly DependencyProperty HeaderSeparatorSizeProperty =
DependencyProperty.Register("HeaderSeparatorSize", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public int HeaderSize
{
get => (int)GetValue(HeaderSizeProperty);
set => SetValue(HeaderSizeProperty, value);
}
public static readonly DependencyProperty HeaderSizeProperty =
DependencyProperty.Register("HeaderSize", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));

public string HeaderText
{
get => (string) GetValue(HeaderTextProperty);
set => SetValue(HeaderTextProperty, value);
}
public static readonly DependencyProperty HeaderTextProperty =
DependencyProperty.Register("HeaderText", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public Thickness HeaderMargin
{
get => (Thickness)GetValue(HeaderMarginProperty);
set => SetValue(HeaderMarginProperty, value);
}
public static readonly DependencyProperty HeaderMarginProperty =
DependencyProperty.Register("HeaderMargin", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));

public Visibility HeaderVisibility
{
get => (Visibility)GetValue(HeaderVisibilityProperty);
set => SetValue(HeaderVisibilityProperty, value);
}
public static readonly DependencyProperty HeaderVisibilityProperty =
DependencyProperty.Register("HeaderVisibility", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
public HorizontalAlignment HeaderHorizontalAlignment
{
get => (HorizontalAlignment)GetValue(HeaderHorizontalAlignmentProperty);
set => SetValue(HeaderHorizontalAlignmentProperty, value);
}
public static readonly DependencyProperty HeaderHorizontalAlignmentProperty =
DependencyProperty.Register("HeaderHorizontalAlignment", typeof(object), typeof(BorderedContainer),
new FrameworkPropertyMetadata(HorizontalAlignment.Left,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
}

如果在另一个项目中包含此控件时(通过样式或直接在xaml属性上(在ViewBox上设置了HeaderHorizontalAlignment属性,则它不会在正确的位置初始化。但是,如果在应用程序运行时更改该值,"热重新加载"将生效并正确放置。同样,如果我直接在generic.xaml中设置它,而不是使用TemplateBinding,它也会按预期工作。这是怎么回事?

注册时,属性类型应为typeof(HorizontalAlignment),而不是typeof(object)

public static readonly DependencyProperty HeaderHorizontalAlignmentProperty =
DependencyProperty.Register("HeaderHorizontalAlignment", typeof(HorizontalAlignment), typeof(BorderedContainer),
new FrameworkPropertyMetadata(HorizontalAlignment.Left,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsParentMeasure));
FrameworkPropertyMetadataOptions.AffectsParentMeasure));

最新更新