我有一个包含按钮样式的资源字典。在按钮的控件模板中,我有4个边框,每个边框代表一个特定的视觉状态 - 正常,悬停,点击和禁用。 4个故事板对象(每个状态一个)将相应边框的可见性翻转为可见,其余边框折叠。这产生了从一个状态到下一个状态的平滑过渡的效果。
代表给定状态的每个边框具有2px边框粗细和10px圆角。边框画笔引用为BorderBrush="{StaticResource BorderBrushName}"
,而边框的背景也以类似方式声明:Background="{StaticResource BackgroundBrushName}"
。
这很好用,但我的任务是做一些调色板切换。由于我们做了很多明确的样式,并且应用程序是一个Silverlight 5应用程序,因为当显式样式引用启动时应用程序爆炸,我无法真正做到主题......然而,这是另一个讨论。
所以我遇到的问题是,“重新设计”应用程序的唯一方法是翻转每个画笔中的颜色并更改每个图像的uri,因为显式样式的广泛使用。
虽然能够在其他控件中执行此操作,但无论我尝试更改相关按钮的外观 - 它都完全没用,我不知道为什么。
我做错了什么?当我隔离代码并将其放入自己的应用程序时,一切正常。在有问题的实际应用程序内...所有其他元素都会更改其颜色/图像,接受相关按钮。
代码附后:
[Theme/Pallete Switching Code]
public static class ThemeManager
{
/// <summary>
/// Does things.
/// </summary>
/// <param name="newTheme"></param>
public static void ChangeTheme(PiranhaTheme newTheme)
{
Uri defaultUri = new Uri("/MyApp;component/Themes/Blue/Blue.xaml", UriKind.Relative);
Uri themeUri = null;
if (newTheme == PiranhaTheme.Blue)
{
themeUri = new Uri("/MyApp;component/Themes/Blue/Blue.xaml", UriKind.Relative);
}
else if (newTheme == PiranhaTheme.Dark)
{
themeUri = new Uri("/MyApp;component/Themes/Dark/Dark.xaml", UriKind.Relative);
}
else
{
themeUri = new Uri("/MyApp;component/Themes/Light/LightTheme.xaml", UriKind.Relative);
}
ResourceDictionary defaultDictionary = ThemeManager.GetResourceDictionary(defaultUri);
ResourceDictionary themeDictionary = ThemeManager.GetResourceDictionary(themeUri);
foreach (var key in defaultDictionary.Keys)
{
var currentValue = App.Current.Resources[key];
var newValue = themeDictionary[key];
if (newValue != null && currentValue != null)
{
if(newValue is SolidColorBrush && currentValue is SolidColorBrush)
{
var newSolidBrush = (SolidColorBrush)newValue;
var currentSolidBrush = (SolidColorBrush)currentValue;
currentSolidBrush.Color = newSolidBrush.Color;
}
else if (newValue is LinearGradientBrush && currentValue is LinearGradientBrush)
{
var newGradientBrush = (LinearGradientBrush)newValue;
var currentGradientBrush = (LinearGradientBrush)currentValue;
currentGradientBrush.GradientStops.Clear();
for (int i = 0; i < newGradientBrush.GradientStops.Count; i++)
{
GradientStop gradientStop = newGradientBrush.GradientStops[i];
GradientStop newGradientStop = new GradientStop();
newGradientStop.Color = gradientStop.Color;
newGradientStop.Offset = gradientStop.Offset;
currentGradientBrush.GradientStops.Add(newGradientStop);
}
}
else if (newValue is BitmapImage && currentValue is BitmapImage)
{
var newBitmapImage = (BitmapImage)newValue;
var currentBitmapImage = (BitmapImage)currentValue;
currentBitmapImage.UriSource = newBitmapImage.UriSource;
}
else if (newValue is Image && currentValue is Image)
{
var newImage = (Image)newValue;
var curImage = (Image)currentValue;
curImage.Source = newImage.Source;
}
}
}
}
private static ResourceDictionary GetResourceDictionary(Uri dictionaryUri)
{
ResourceDictionary result = new ResourceDictionary();
try
{
Application.LoadComponent(result, dictionaryUri);
}
catch { }
return result;
}
}
[App.xaml]
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyApp;component/Assets/BlueTheme.xaml"/>
<ResourceDictionary Source="/MyApp;component/Assets/ButtonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
[Button Style - On It's Own Resource Dictionary]
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="MainLaunchMenuButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RegularState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HoverState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MousePressedState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisabledState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RegularState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HoverState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MousePressedState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisabledState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RegularState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HoverState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MousePressedState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisabledState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RegularState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HoverState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MousePressedState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisabledState" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="RegularState" Visibility="Visible" BorderBrush="{StaticResource MainLaunchMenuButtonRegularStateBorderBrush}" Background="{StaticResource MainLaunchMenuButtonHoverStateBackgroundBrush}" BorderThickness="2" CornerRadius="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Border x:Name="HoverState" Visibility="Collapsed" BorderBrush="{StaticResource MainLaunchMenuButtonHoverStateBorderBrush}" Background="{StaticResource MainLaunchMenuButtonHoverStateBackgroundBrush}" BorderThickness="2" CornerRadius="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Border x:Name="MousePressedState" Visibility="Collapsed" BorderBrush="{StaticResource MainLaunchMenuButtonPressedStateBorderBrush}" Background="{StaticResource MainLaunchMenuButtonPressedStateBackgroundBrush}" BorderThickness="2" CornerRadius="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Border x:Name="DisabledState" Visibility="Collapsed" BorderBrush="{StaticResource MainLaunchMenuButtonDisabledStateBorderBrush}" Background="{StaticResource MainLaunchMenuButtonDisabledStateBackgroundBrush}" BorderThickness="2" CornerRadius="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
[Blue Theme]
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="MainWindowBackground" Color="#FF003A6D" />
<SolidColorBrush x:Key="MainLaunchMenuButtonRegularStateBorderBrush" Color="#78A4D4"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonRegularStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF002141" Offset="1"/>
<GradientStop Color="#FF1C4973"/>
<GradientStop Color="#FF002141" Offset="0.6"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MainLaunchMenuButtonHoverStateBorderBrush" Color="#FFFF8500"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonHoverStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF002141" Offset="1"/>
<GradientStop Color="#FF1C4973"/>
<GradientStop Color="#FF002141" Offset="0.6"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MainLaunchMenuButtonPressedStateBorderBrush" Color="#002141"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonPressedStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFFF8500" Offset="0.6"/>
<GradientStop Color="#FFFF8500" Offset="1"/>
<GradientStop Color="#FFFF9B43"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MainLaunchMenuButtonDisabledStateBorderBrush" Color="#8078A4D4"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonDisabledStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#80123C62" Offset="0.6"/>
<GradientStop Color="#80002141" Offset="1"/>
<GradientStop Color="#801C4973"/>
</LinearGradientBrush>
</ResourceDictionary>
[Light Theme]
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="MainWindowBackground" Color="#333333" />
<SolidColorBrush x:Key="MainLaunchMenuButtonRegularStateBorderBrush" Color="#2F2F2F"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonRegularStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF404040"/>
<GradientStop Color="#FF4E4E4E" Offset="0.6"/>
<GradientStop Color="#FF535353" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MainLaunchMenuButtonHoverStateBorderBrush" Color="#28728B"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonHoverStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF46C8F6"/>
<GradientStop Color="#FF42C4F2" Offset="0.6"/>
<GradientStop Color="#FF34ADD8" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MainLaunchMenuButtonPressedStateBorderBrush" Color="#2F2F2F"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonPressedStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF46C8F6"/>
<GradientStop Color="#FF42C4F2" Offset="0.6"/>
<GradientStop Color="#FF34ADD8" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="MainLaunchMenuButtonDisabledStateBorderBrush" Color="#802F2F2F"/>
<LinearGradientBrush x:Key="MainLaunchMenuButtonDisabledStateBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#804D4D4D" Offset="0.6"/>
<GradientStop Color="#80505050" Offset="1"/>
<GradientStop Color="#80404040"/>
</LinearGradientBrush>
</ResourceDictionary>
答案 0 :(得分:0)
好的,所以我找到了这个有趣问题的解决方案。问题是虽然App.Current.Resources["Key"]
将检索特定资源,但这并不意味着它是该资源的唯一实例。
因此,如果一个ResourceDictionary
通过MergedDictionaries
属性引用另一个{{1}},则可以有效地创建所引用内容的新实例。因此,如果我们有App.xaml,资源字典A和B,以及A中的样式引用B中声明的键,那么实际上我们可以有两个B实例 - 一个在app.xaml中声明引用时,另一个一个在A.
因此,如果我们想要更改B中声明的画笔的颜色,那么我们必须递归(找到该画笔的每个实例)。我们会通过遍历每个字典和它的合并字典集合,以及它们合并的字典的合并字典等来完成,并且只要其键存在(在当前字典中),就更改画笔的颜色代码,并且在该键下声明的资源属于同一类型。