如何扩展从UserControl中的父容器继承的样式

本文关键字:样式 继承 UserControl 何扩展 扩展 | 更新日期: 2023-09-27 18:15:37

我有一个StackPanel里面有一个UserControl:

<StackPanel>
    <local:MyUC/>
</StackPanel>

UserControl包含各种TextBoxes和其他控件,通过ResourceDictionary设置它们的样式,以实现整个应用程序的通用外观。对于TextBox, ResourceDictionary条目看起来像这样:

<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
    <Setter Property="DockPanel.Dock" Value="Top"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="MaxWidth" Value="{Binding RelativeSource={RelativeSource AncestorType=Border},Path=ActualWidth}"/>
    <Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
</Style>

现在我想将父控件(StackPanel)中的默认样式应用于UserControl中的所有TextBox es,因此我可以将TextBox es的IsReadOnly -属性绑定到仅在父模型中可用的属性:

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Model.State}" Value="ReadOnly">
                    <Setter Property="IsReadOnly" Value="True"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Resources>
    <local:MyUC/>
</StackPanel>

不幸的是,在UserControlResourceDictionary中定义的TargetType="{x:Type TextBox}"的默认样式覆盖了我试图在父StackPanel中设置的样式。

我如何实现扩展的默认样式,是在StackPanel.Resources内定义的默认样式在UserControlResourceDictionary中定义的,而不是覆盖它?

如何扩展从UserControl中的父容器继承的样式

这就是我所做的,我从来没有遇到过问题:

在ResourceDictionary:

<Style x:Key="TextBoxBase" TargetType="{x:Type TextBox}">
    <!-- Default styles go here -->
</Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxBase}"/>

这确保了除非另有规定,所有的文本框都将具有TextBoxBase样式,而不是更多或更少。

当定义必须具有上述属性的样式时,您可以这样定义样式(在您的情况下,此样式是StackPanel的一部分):

<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxBase}">
    <Style.Triggers>
        <!-- These triggers should be in ADDITION to triggers defined in TextBoxBase.-->
        <DataTrigger Binding="{Binding Model.State}" Value="ReadOnly">
            <Setter Property="IsReadOnly" Value="True"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

另一个问题可能是您为控件中包含的TextBoxes定义了样式。如果你的目标样式的文本框是唯一的控件,他们被包含在,为什么不在控件本身定义它们?要做到这一点,只需在控件上绑定一个对ViewModel的引用,然后在控件中使用该引用,使用上述方法将DataTrigger应用于每个TextBox。