WPF:通过关键字处理嵌套样式

4

我有一个相当复杂的WPF UserControl,需要大量自定义样式,并且对于相同的控件类型需要多种不同的样式。这些样式在其他地方都没有使用过。

我想使用嵌套样式(使用Style.Resources)作为一种命名空间机制,如下所示:

示例用户控件:

<UserControl Style="{StaticResource AwesomeControl}>
    <Grid>
        <Button Style="{StaticResource ButtonA}"/>
        <Button Style="{StaticResource ButtonB}"/>
    </Grid>
</UserControl>

我希望定义我的样式的方式:

<ResourceDictionary>
    <Style TargetType="UserControl" x:Key="AwesomeControl">
        <Style.Resources>
            <Style TargetType="Button" x:Key="ButtonA"> </Style>
            <Style TargetType="Button" x:Key="ButtonB"> </Style>
        </Style.Resources>
    </Style>
</ResourceDictionary>

然而,这样做是行不通的。根据我所了解的,好像无法通过键来访问嵌套样式。(我已经搜索了很多,但没有找到一个单一的例子能够做到这样。)
如果我把所有样式都保留在顶级,那么这个问题就容易解决了。然而,我必须将它们的键更改为类似于AwesomeControlButtonA之类的内容,以区分它们与应用程序中其他部分。
这对我来说并不理想。
所以我的问题是:
像上面代码中我正在尝试的这样做是有可能的吗?如果不行,是否有其他命名空间的方法可以使用,以防止出现诸如 AwesomeControlButtonA 之类的难看的键名?

你无法避免拥有AwesomeControlButtonA键或将它们变成AwesomeControl.ButtonA,其中AwesomeControl可以被省略,因为资源键查找是普通的字典搜索。你只能使用作用域(将其视为局部变量)。如果你计划全局持有样式,则会使用AwesomeControlButtonA。考虑在最合适的范围内定义按钮,这样你就不需要长键了。还有BasedOn来实现一种继承(意味着更少的键)。 - Sinatr
不要忘记,这个简单的字典是在“可视化”期间构建的。因此,并没有一个简单的字典。VisualTree的元素根据其在可视树中的位置具有不同的字典。 - sac1
1个回答

7
也许使用DynamicResource可以解决你的问题。
<Grid>
    <Button Style="{DynamicResource ButtonA}"/>
    <Button Style="{DynamicResource ButtonB}"/>
</Grid>

在上下文中:

<Grid>
    <Grid.Resources>
        <Style x:Key="AW" TargetType="UserControl">
            <Style.Resources>
                <Style TargetType="Button" x:Key="AB">
                    <Setter Property="Background" Value="Red" />
                </Style>
                <Style TargetType="Button" x:Key="BB">
                    <Setter Property="Background" Value="Yellow" />
                </Style>
            </Style.Resources>
        </Style>
        <Style x:Key="AR" TargetType="UserControl">
            <Style.Resources>
                <Style TargetType="Button" x:Key="AB">
                    <Setter Property="Background" Value="Green" />
                </Style>
                <Style TargetType="Button" x:Key="BB">
                    <Setter Property="Background" Value="Blue" />
                </Style>
            </Style.Resources>
        </Style>
    </Grid.Resources>

    <StackPanel>
        <UserControl Style="{StaticResource AW}">
            <StackPanel>
                <Button Content="A" Style="{DynamicResource AB}" />
                <Button Content="A" Style="{DynamicResource BB}" />
            </StackPanel>
        </UserControl>
        <UserControl Style="{StaticResource AR}">
            <StackPanel>
                <Button Content="A" Style="{DynamicResource AB}" />
                <Button Content="A" Style="{DynamicResource BB}" />
            </StackPanel>
        </UserControl>
    </StackPanel>
</Grid>

enter image description here


1
我没有意识到DynamicResource可以这样使用。感谢提供非常生动的例子!(虽然我没有投票,但你的答案现在看起来更美观了。)我会研究一下这个,如果它对我有用(/如果没有更好的答案),我会接受你的答案。 - amulware
这就是为什么存在DynamicResource的原因。当您将Style应用于UserControl时,您动态更改了ResourceDictionary中的ABBB样式。DynamicResource注意到了它 - 因为它是一个表达式,而不是硬编码链接 - 并刷新自己。StaticResource无法刷新。它在XAML解析期间加载,没有办法替换它。 - sac1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接