简体   繁体   中英

WPF custom control: HorizontalAlignment style setting on ViewBox does not initialize correctly

I have the following custom control in a .NET 5 WPF project:

<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>

With the following definition:

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));

    }

If I set the HeaderHorizontalAlignment property on the ViewBox when including this control in another project (either via a style or directly on the xaml property), it does not initialize in the correct position. However, if I change the value while the application is running, Hot Reload kicks in and places it correctly. Likewise, if I set it directly in the generic.xaml rather than using the TemplateBinding, it works as expected. What's going on here?

The property type should be typeof(HorizontalAlignment) instead of typeof(object) when you register it:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM