在运行时更改MergedDictionaries

时间:2013-12-26 11:14:01

标签: c# wpf exception themes scrollbar

我目前正在开发一个WPF应用程序,允许用户在运行时更改其主题(无需重启)。我目前正在使用此处的代码:

http://svetoslavsavov.blogspot.de/2009/07/switching-wpf-interface-themes-at.html

我用Try语句对其进行了修改:

private static void ApplyTheme(FrameworkElement targetElement, Uri dictionaryUri)
    {
        if (targetElement == null) return;

        try
        {
            ResourceDictionary themeDictionary = null;
            if (dictionaryUri != null)
            {
                themeDictionary = new ResourceDictionary();
                themeDictionary.Source = dictionaryUri;

                targetElement.Resources.MergedDictionaries.Insert(0, themeDictionary);
            }

            List<ResourceDictionary> existingDictionaries =
                (from dictionary in targetElement.Resources.MergedDictionaries.OfType<ResourceDictionary>()
                 select dictionary).ToList();

            foreach (ResourceDictionary thDictionary in existingDictionaries)
            {
                if (themeDictionary == thDictionary) continue;
                try
                {
                    targetElement.Resources.MergedDictionaries.Remove(thDictionary);
                }
                catch { }
            }
        }
        finally { }
    }

但如果我在我的应用程序中设置了ScrollBars样式,它就不会起作用。它第一次总是将相同的ComboBox变成一个矩形,你不能再使用它了:

http://goo.gl/eNC2m0

第二次抛出异常:

Unable to cast object of type 'MS.Internal.NamedObject' to type 'System.Windows.FrameworkTemplate'.

如果我删除Try语句,它会在第一次抛出异常。

ScrollBar样式如下所示:

<!-- Colors -->
<Color x:Key="Accent">#FFFEB809</Color>
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource Accent}"/>
<Color x:Key="AccentConsole">#22FEB809</Color>
<SolidColorBrush x:Key="AccentConsoleBrush" Color="{StaticResource AccentConsole}"/>
<Color x:Key="AccentLight">#FFFFDB82</Color>
<SolidColorBrush x:Key="AccentLightBrush" Color="{StaticResource AccentLight}"/>
<Color x:Key="AccentLightConsole">#22FFDB82</Color>
<SolidColorBrush x:Key="AccentLightConsoleBrush" Color="{StaticResource AccentLightConsole}"/>
<Color x:Key="AccentText">#FFFFFFFF</Color>
<SolidColorBrush x:Key="AccentTextBrush" Color="{StaticResource AccentText}"/>
<Color x:Key="Border">#FFCCCCCC</Color>
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource Border}"/>
<Color x:Key="CaptionBar">#FFFCFCFC</Color>
<SolidColorBrush x:Key="CaptionBarBrush" Color="{StaticResource CaptionBar}"/>
<Color x:Key="ConsoleBackground">#FF222222</Color>
<SolidColorBrush x:Key="ConsoleBackgroundBrush" Color="{StaticResource ConsoleBackground}"/>
<Color x:Key="ControlBackground">White</Color>
<SolidColorBrush x:Key="ControlBackgroundBrush" Color="{StaticResource ControlBackground}"/>
<Color x:Key="NavigationHeader">#88000000</Color>
<SolidColorBrush x:Key="NavigationHeaderBrush" Color="{StaticResource NavigationHeader}"/>
<Color x:Key="Window">#FFFAFAFA</Color>
<SolidColorBrush x:Key="WindowBrush" Color="{StaticResource Window}"/>

<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="Margin" Value="2"/>
    <Style.Triggers>
        <Trigger Property="Orientation" Value="Horizontal">
            <Setter Property="Template" Value="{StaticResource HorizontalScrollBar}"/>
            <Setter Property="Height" Value="24"/>
        </Trigger>
        <Trigger Property="Orientation" Value="Vertical">
            <Setter Property="Template" Value="{StaticResource VerticalScrollBar}"/>
            <Setter Property="Width" Value="24"/>
        </Trigger>
    </Style.Triggers>
</Style>
<ControlTemplate x:Key="HorizontalScrollBar" TargetType="{x:Type ScrollBar}">
    <Grid>
        <Border Background="#22000000" CornerRadius="4">
            <Track Name="PART_Track">
                <Track.DecreaseRepeatButton>
                    <RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageLeftCommand"/>
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <!-- The problem occurs here -->
                    <Thumb Style="{StaticResource HorizontalScrollBarThumb}"/>
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageRightCommand"/>
                </Track.IncreaseRepeatButton>
            </Track>
        </Border>
    </Grid>
</ControlTemplate>
<ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
    <Grid>
        <Border Background="#22000000" CornerRadius="4">
            <Track Name="PART_Track" IsDirectionReversed="True">
                <Track.DecreaseRepeatButton>
                    <RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageUpCommand"/>
                </Track.DecreaseRepeatButton>
                <Track.Thumb>
                    <!-- The problem occurs here -->
                    <Thumb Style="{StaticResource VerticalScrollBarThumb}"/>
                </Track.Thumb>
                <Track.IncreaseRepeatButton>
                    <RepeatButton Style="{StaticResource ScrollBarPageButton}" Command="ScrollBar.PageDownCommand"/>
                </Track.IncreaseRepeatButton>
            </Track>
        </Border>
    </Grid>
</ControlTemplate>
<Style x:Key="HorizontalScrollBarThumb" TargetType="{x:Type Thumb}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Semibold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="24"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="24"/>
                    </Grid.ColumnDefinitions>
                    <RepeatButton Style="{StaticResource LeftScrollBarLineButton}" Command="ScrollBar.LineLeftCommand"/>
                    <Border Name="Base" Background="{StaticResource ControlBackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,1,0,1" Grid.Column="1">
                        <TextBlock Text="" FontFamily="Segoe UI Symbol" Foreground="#FF585858" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Border>
                    <RepeatButton Style="{StaticResource RightScrollBarLineButton}" Command="ScrollBar.LineRightCommand" Grid.Column="2"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="VerticalScrollBarThumb" TargetType="{x:Type Thumb}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Semibold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="24"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="24"/>
                    </Grid.RowDefinitions>
                    <RepeatButton Style="{StaticResource TopScrollBarLineButton}" Command="ScrollBar.LineUpCommand"/>
                    <Border Name="Base" Background="{StaticResource ControlBackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1,0,1,0" Grid.Row="1">
                        <TextBlock Text="" FontFamily="Segoe UI Symbol" Foreground="#FF585858" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Border>
                    <RepeatButton Style="{StaticResource BottomScrollBarLineButton}" Command="ScrollBar.LineDownCommand" Grid.Row="2"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="LeftScrollBarLineButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border Name="Base" Background="{StaticResource ControlBackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" CornerRadius="4,0,0,4" BorderThickness="1,1,0,1">
                    <TextBlock Text="" Foreground="{TemplateBinding Foreground}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Base" Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <LinearGradientBrush.RelativeTransform>
                                        <RotateTransform Angle="-90"/>
                                    </LinearGradientBrush.RelativeTransform>
                                    <GradientStop Color="{StaticResource AccentLight}" Offset="0"/>
                                    <GradientStop Color="{StaticResource ControlBackground}" Offset="1"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="RightScrollBarLineButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border Name="Base" Background="{StaticResource ControlBackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" CornerRadius="0,4,4,0" BorderThickness="0,1,1,1">
                    <TextBlock Text="" Foreground="{TemplateBinding Foreground}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Base" Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <LinearGradientBrush.RelativeTransform>
                                        <RotateTransform Angle="90"/>
                                    </LinearGradientBrush.RelativeTransform>
                                    <GradientStop Color="{StaticResource AccentLight}" Offset="0"/>
                                    <GradientStop Color="{StaticResource ControlBackground}" Offset="1"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="TopScrollBarLineButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border Name="Base" Background="{StaticResource ControlBackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" CornerRadius="4,4,0,0" BorderThickness="1,1,1,0">
                    <TextBlock Text="" Foreground="{TemplateBinding Foreground}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Base" Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <GradientStop Color="{StaticResource AccentLight}" Offset="0"/>
                                    <GradientStop Color="{StaticResource ControlBackground}" Offset="1"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="BottomScrollBarLineButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border Name="Base" Background="{StaticResource ControlBackgroundBrush}" BorderBrush="{StaticResource BorderBrush}" CornerRadius="0,0,4,4" BorderThickness="1,0,1,1">
                    <TextBlock Text="" Foreground="{TemplateBinding Foreground}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="Base" Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                    <GradientStop Color="{StaticResource AccentLight}" Offset="1"/>
                                    <GradientStop Color="{StaticResource ControlBackground}" Offset="0"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ScrollBarPageButton" TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Foreground" Value="#FF585858"/>
    <Setter Property="FontFamily" Value="Segoe UI Semibold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Padding" Value="8"/>
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

但是当我用<Thumb Style="{StaticResource HorizontalScrollBarThumb}"/>替换<Thumb Style="{StaticResource VerticalScrollBarThumb}"/><Thumb/>时,它就可以了。

我在Thumb样式中找不到任何可能导致此问题的内容。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

这是因为模板的顺序。只需更改下图中给出的模板顺序即可。 StaticResources应该在XAML中引用之前进行解析。

enter image description here

上面粘贴的XAML代码也缺少一些画笔资源,如AccentLight,ControlBackgroundBrush。我不知道您的应用程序中是否在适当的层次结构中定义了这些资源。检查一下。