WPF 样式导致循环

发布于 2024-08-12 17:58:42 字数 1262 浏览 7 评论 0原文

为什么以下 XAML 会导致某些主题出现堆栈溢出异常?

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="ExpressionLight.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
            <Setter Property="Margin" Value="5"/>
        </Style>
        <Style TargetType="{x:Type Button}"  BasedOn="{StaticResource BaseButtonStyle}"/>
    </ResourceDictionary>
</Application.Resources>

我尝试过在互联网上找到的几个主题,其中大约一半会导致异常。

是否有另一种方法可以将命名的 Style 应用为默认值?

编辑:

问题是主题将默认样式添加到资源字典中(名为System.Windows.Control.Button的条目) )。由于字典只能包含每个键的单个条目,因此不可能在同一资源字典中添加新的默认值。

不知道为什么它会导致“stackoverflow”而不是“重复键”异常。这可能是因为对可能包含重复键的合并字典进行了特殊处理。

解决方案是在代码中应用命名的 Style 作为默认值:

void AppStartup(object sender, StartupEventArgs args) {
    this.Resources[typeof(Button)] = this.Resources["BaseButtonStyle"];
    ....
}

由于 BaseButtonStyle 静态绑定到主题,因此当然不可能使用此解决方案在运行时更改主题。

Why does the following XAML cause a stack overflow exception with some themes?

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="ExpressionLight.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
            <Setter Property="Margin" Value="5"/>
        </Style>
        <Style TargetType="{x:Type Button}"  BasedOn="{StaticResource BaseButtonStyle}"/>
    </ResourceDictionary>
</Application.Resources>

I have tried several themes found on internet and about half of them causes the exception.

Is there another way to apply a named Style as default?

Edit:

The problem is that the Theme adds the default style to the resource dictionary (an entry with the name System.Windows.Control.Button). Since a dictionary can only contain a single entry for each key it is not possible add a new default within the same resource dictionary.

Don't know why it leads to a "stackoverflow" instead of a "duplicate key" exception. It is probably because of the special handling of merged dictionaries which can contain duplicate keys.

The solution is to apply the named Style as default in code:

void AppStartup(object sender, StartupEventArgs args) {
    this.Resources[typeof(Button)] = this.Resources["BaseButtonStyle"];
    ....
}

Since the BaseButtonStyle is staticly bound to the theme it is of course not possible to change theme at runtime with this solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清秋悲枫 2024-08-19 17:58:42

您在此代码中存在循环依赖关系:

<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Margin" Value="5"/>
</Style>

此样式表示它适用于 TargetType Button,这很好。
它还说它是基于为 TargetType Button 定义的 Style,这就是 this 本身。
最好为之前的样式分配一个键,然后在 BasedOn 中使用该键。

编辑:

再次查看您的代码后,您的样式与 ExpressionLight.xaml 中定义的样式之间似乎存在循环引用。解决方法是将资源放置在不同级别。

<Window.Resources>
<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ExpressionLight.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
    <Grid.Resources>
    <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
        <Setter Property="Margin" Value="5"/>
    </Style>
    <Style TargetType="{x:Type Button}"  BasedOn="{StaticResource BaseButtonStyle}"/>
    </Grid.Resources>
    ............
    ...........
    ...........
</Grid>

you are having circular dependency in this code:

<Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Margin" Value="5"/>
</Style>

this style says that it is for TargetType Button, thats fine.
it also says that it is BasedOn the Style defined for TargetType Button, which is this itself.
Better to assign a key to the previous Style and then use that key in BasedOn.

EDIT:

After going through your code again it seems that there is a circular reference between your style and the style defined in ExpressionLight.xaml. A workaround would be to place resources at different levels.

<Window.Resources>
<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ExpressionLight.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
    <Grid.Resources>
    <Style x:Key="BaseButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
        <Setter Property="Margin" Value="5"/>
    </Style>
    <Style TargetType="{x:Type Button}"  BasedOn="{StaticResource BaseButtonStyle}"/>
    </Grid.Resources>
    ............
    ...........
    ...........
</Grid>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文