样式化派生的UserControl会使其消失

时间:2018-05-31 04:45:49

标签: c# wpf

我有一个控件PaneBase,它派生自UserControl。没有XAML,它只是一个控件。有问题的UserControl类型是来自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:

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

EquationPane.xaml.cs

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

到目前为止,所有这些都有效,当我在窗口中包含EquationPane时,它会正常显示:

<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 个答案:

答案 0 :(得分:1)

隐式样式不会自动应用于派生类型。要将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}}"/>

答案 1 :(得分:1)

  

为什么会这样?

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>

...它不再有模板,这就是你在窗口中看不到控件的原因。