在声明为静态资源并在控件tempate中使用时,在运行时更改LinearGradientBrush的GradientStops

时间:2013-11-26 03:53:35

标签: silverlight silverlight-4.0 silverlight-5.0

我有一个包含按钮样式的资源字典。在按钮的控件模板中,我有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>

1 个答案:

答案 0 :(得分:0)

好的,所以我找到了这个有趣问题的解决方案。问题是虽然App.Current.Resources["Key"]将检索特定资源,但这并不意味着它是该资源的唯一实例。

因此,如果一个ResourceDictionary通过MergedDictionaries属性引用另一个{{1}},则可以有效地创建所引用内容的新实例。因此,如果我们有App.xaml,资源字典A和B,以及A中的样式引用B中声明的键,那么实际上我们可以有两个B实例 - 一个在app.xaml中声明引用时,另一个一个在A.

因此,如果我们想要更改B中声明的画笔的颜色,那么我们必须递归(找到该画笔的每个实例)。我们会通过遍历每个字典和它的合并字典集合,以及它们合并的字典的合并字典等来完成,并且只要其键存在(在当前字典中),就更改画笔的颜色代码,并且在该键下声明的资源属于同一类型。