代码之家  ›  专栏  ›  技术社区  ›  laptou

设置派生UserControl的样式会导致其消失

  •  1
  • laptou  · 技术社区  · 8 年前

    我有控制权 PaneBase ,其派生自 UserControl .没有XAML,它只是一个控件。这个 用户控件 所讨论的类型是Catel提供的类型,但在使用 System.Windows.Controls.UserControl 。

    public class PaneBase : UserControl
    {
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title",
                                        typeof(string),
                                        typeof(PaneBase),
                                        new PropertyMetadata(default(string)));
    
        public string Title
        {
            get => (string) GetValue(TitleProperty);
            set => SetValue(TitleProperty, value);
        }
    }
    

    我有另一个控制 EquationPane 其来源于 PaneBase公司 并且具有XAML:

    等式窗格。xaml

    <local:PaneBase x:Class="EngineersToolkit.Windows.Views.Panes.EquationPane"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:catel="http://schemas.catelproject.com" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:local="clr-namespace:EngineersToolkit.Windows.Views.Panes"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    Title="Equation"
                    d:DataContext="{d:DesignData EquationPaneViewModel}" d:DesignHeight="450" d:DesignWidth="800"
                    mc:Ignorable="d">
        <Grid>
            <TextBox Width="150" Height="30"
                     Text="{Binding Equation, Mode=TwoWay}" />
    
        </Grid>
    </local:PaneBase>
    

    等式窗格。xaml。cs公司

    public partial class EquationPane
    {
        public EquationPane()
        {
            InitializeComponent();
            DataContext = new EquationPaneViewModel();
        }
    }
    

    到目前为止,当我包括 等式窗格 在窗口中,它会正常显示:

    <Grid>
        <panes:EquationPane Width="100" Height="100"
                            HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                            Background="Aqua" />
    
    </Grid>
    

    enter image description here

    如果我尝试设置控件样式,它将继续正常工作:

    <Style TargetType="{x:Type panes:EquationPane}">
        <Setter Property="Background" Value="Red" />
    </Style>
    

    然而,如果我将风格定位为 PaneBase公司 相反如果我改变 TargetType 若要使用PaneBase,则不应用该样式。但是,如果我重写 PaneBase公司 像这样:

    static PaneBase()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(PaneBase),
                                                 new FrameworkPropertyMetadata(
                                                     typeof(PaneBase)));
    }
    

    然后控件停止渲染,留下一个空白窗口。为什么会这样?

    2 回复  |  直到 8 年前
        1
  •  1
  •   mm8    8 年前

    为什么会这样?

    WPF控件是“无外观”的,这意味着除非为它们定义模板,否则它们没有外观。

    以下说明为定义了默认样式 PaneBase 在里面 themes/generic.xaml :

    static PaneBase()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(PaneBase),
                                             new FrameworkPropertyMetadata(
                                                 typeof(PaneBase)));
    }
    

    然后应定义这样的样式:

    <Style TargetType="local:PaneBase">
        <Setter Property="Background" Value="Red" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type UserControl}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    如果在中删除静态构造函数 PanelBase 它将从 UserControl 基类。

    如果定义 Style 对于 PaneBase公司 像这样:

    <Style TargetType="{x:Type local:PaneBase}">
        <Setter Property="Background" Value="Red" />
    </Style>
    

    。。。它不再有模板,这就是为什么您在窗口中看不到控件的原因。

        2
  •  1
  •   Shivani Katukota    8 年前

    隐式样式不会自动应用于派生类型。要将PaneBase样式应用于EquationPane,可以执行以下操作之一:

    1、将其写在您的EquationPane上。xaml。cs公司

    public EquationPane() 
        {
            this.SetResourceReference(StyleProperty, typeof(PaneBase));
        }
    

    2、明确提供使用EquationPane的样式

    <panes:EquationPane Style="{DynamicResource {x:Type PaneBase}}"/>
    

    3、定义基于父样式的样式

    <Style x:Key="{x:Type PaneBase}" TargetType="{x:Type PaneBase}">
          <Setter Property="Background" Value="Red" />
    </Style>
    
    <Style TargetType="{x:Type panes:EquationPane}" BasedOn="{StaticResource {x:Type PaneBase}}"/>