【问题标题】:Inversion of inheritance in WPF stylesWPF 样式中的继承反转
【发布时间】:2013-07-29 19:11:13
【问题描述】:

我有一个包含按钮的 UserControl:

<Button Content="Button"/>

还有一种风格:

<Style TargetType="Button">
    <Setter Property="Background" Value="Blue"/>
</Style>

父窗口(或另一个用户控件)可以设置另一种更通用的样式:

<Style TargetType="Button">
    <Setter Property="Background" Value="Red"/>
</Style>

结果是(很明显)父按钮将具有更一般的样式(红色),而我的用户控件将具有更具体的样式(蓝色)。


我想知道如何反转这种行为以实现诸如在我的自定义用户控件中设置默认样式之类的东西,然后如果需要,可以在父控件或窗口中覆盖?

关键是,默认样式首先在自定义用户控件中定义,并被其父级自动覆盖。这就是我称之为倒置的方式。


解决方案的假想示例可能如下所示:

<Style TargetType="Button" StylePriority="Default">
    <Setter Property="Background" Value="Blue"/>
</Style>

StylePriority 表示如果没有为该按钮定义其他样式,则应应用默认样式。

【问题讨论】:

  • 如果您想在父控件中使用默认样式,为什么还要在您的usercontrol 中再次定义另一种样式?
  • @Bolu:编辑以更好地理解。我想在用户控件中定义默认样式,但是我希望能够在父窗口中覆盖它。假设:蓝色按钮在自定义控件中定义为默认值。在父窗口中覆盖它以获得红色按钮。
  • 我不是 100% 确定,但我认为没有一种简单的方法可以做你想做的事情,就像反转 VisualTree :)

标签: c# wpf


【解决方案1】:

您可以使用动态资源。

一个用户控件:

<UserControl x:Class="Example.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Example">
    <UserControl.Resources>
        <Style TargetType="local:UserControl1">
            <Style.Resources>
                <Style TargetType="Button" x:Key="UserControl1.DefaultButtonStyle">
                    <Setter Property="Background" Value="Red"/>
                </Style>
            </Style.Resources>
        </Style>
    </UserControl.Resources>

    <Button Content="UserControlButton" Style="{DynamicResource UserControl1.DefaultButtonStyle}"/>
</UserControl>

还有一个窗口:

<Window x:Class="Example.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Example">

    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Background" Value="Blue" />
        </Style>
    </Window.Resources>

    <StackPanel>
        <local:UserControl1 >
            <local:UserControl1.Resources>
                <Style x:Key="UserControl1.DefaultButtonStyle" TargetType="Button"
                    BasedOn="{StaticResource {x:Type Button}}">
                    <Setter Property="FontSize" Value="40" />
                </Style>
            </local:UserControl1.Resources>
        </local:UserControl1>
        <Button Content="WindowButton" />
    </StackPanel>
</Window>

如果删除窗口中控件的样式,将应用默认的用户控件按钮样式。

【讨论】:

    【解决方案2】:

    在您的UserControl 中为按钮颜色创建一个依赖属性,然后绑定到它。您可以为该属性指定默认值蓝色。

    public static readonly DependencyProperty ButtonColorProperty = 
        DependencyProperty.Register("ButtonColor", typeof(Color), typeof(MyUserControl),
        new PropertyMetadata(Colors.Blue));
    
    public Color State
    {
        get { return (Color)this.GetValue(ButtonColorProperty); }
        set { this.SetValue(ButtonColorProperty, value); } 
    }
    
    <UserControl ...
                 x:Name="root">
        <Button Content="Button" Background="{Binding ElementName=root, Path=ButtonColor}" />
    </UserControl>
    

    然后在要使用UserControl 的地方将该属性设置为红色。

    <local:MyUserControl ButtonColor="Red" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-07
      • 1970-01-01
      • 2010-11-09
      • 2021-10-30
      • 1970-01-01
      相关资源
      最近更新 更多