#c# #wpf #.net-core
Вопрос:
У меня есть следующий пользовательский элемент управления в проекте .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));
}
Если я установлю свойство HeaderHorizontalAlignment в поле просмотра при включении этого элемента управления в другой проект (либо с помощью стиля, либо непосредственно в свойстве xaml), он не инициализируется в правильном положении. Однако, если я изменю значение во время работы приложения, произойдет горячая перезагрузка и оно будет установлено правильно. Аналогично, если я установлю его непосредственно в generic.xaml, а не с помощью привязки шаблонов, он будет работать так, как ожидалось. Что здесь происходит?
Комментарии:
1. Тип недвижимости должен быть
typeof(HorizontalAlignment)
указан вместоtypeof(object)
того, когда вы регистрируете недвижимость.2. @mm8 Это сделало свое дело. Можете ли вы объяснить, почему это имеет значение? Я бы ожидал, что актерского состава будет достаточно. Это не проблема ни для одного из моих других свойств, и когда я устанавливаю тип по умолчанию для некоторых из них на ожидаемый тип, я получаю исключения, связанные с несоответствиями типов.
Ответ №1:
Тип свойства должен быть 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));