代码之家  ›  专栏  ›  技术社区  ›  adrianm

导致循环的WPF样式

  •  0
  • adrianm  · 技术社区  · 15 年前

    为什么下面的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 作为默认值?

    编辑:

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

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

    解决方案是应用 风格 作为代码中的默认值:

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

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

    1 回复  |  直到 13 年前
        1
  •  2
  •   viky    15 年前

    此代码中存在循环依赖项:

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

    这个样式表示它是针对TargetType按钮的,很好。 它还表示,它基于为TargetType按钮定义的样式,也就是它本身。 最好为前一个样式指定一个键,然后在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>