簡體   English   中英

WPF 自定義控件:ViewBox 上的 HorizontalAlignment 樣式設置未正確初始化

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

我在 .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 屬性,則它不會在正確的 position 中初始化。 但是,如果我在應用程序運行時更改該值,熱重載就會啟動並正確放置它。 同樣,如果我直接在 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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM