none
如何做到全局开关动画功能 RRS feed

  • 问题

  • 我在开发一个系统,希望如果配置较差的用户不使用动画特效,比如:3D旋转特效等。或者能让用户自定义系统是否显示特效。
    我该如何去做呢?
    Sonny.Lin
    • 已编辑 qing2000 2011年6月6日 5:25 错别字
    2011年6月6日 5:25

答案

  • 我个人认为这个是一个结构设计的问题,是没有一个很明确的答案的。不过我有一个很好的想法,你可以参考下:

     

    我们需要将所有的特效动画设计到一个资源字典中,然后我们还需要设计另外一套没有特效的,在运行时我们只需要控制加载哪套资源字典就可以实现不同的效果了,如果你要特效,就把特效资源加载到 Application.Current.Resources.MergedDictionaries 中去,否则就加载另一套。这一点就和加载不同的控件主题一样,我们可以在运行时切换所有的基本控件是否使用Win7的Aero主题还是切换使用经典主题。关于动态切换主题,你可以看看下面的链接:

    http://blog.xamltemplates.net/?p=20

     

    Sincerely,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年6月6日 8:45
    版主
  • 亲爱的Bob,You are great!
    根据你的提示,我已完成了动画全局开启与关闭。在此我介绍详细做法和代码。
    效果图:
    初始状态http://hi.csdn.net/attachment/201106/8/63407_1307546160YU7h.png
    鼠标移动到矩形上颜色更改http://hi.csdn.net/attachment/201106/8/63407_1307546160YU7h.png

    1.建立两个资源字典,分别为Storyboards.xaml和NonStoryboards.xaml
    Storyboards.xaml里放有动画的内容
    见项目文件截图:http://hi.csdn.net/attachment/201106/8/63407_1307546171UPyu.png

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    	<Storyboard x:Key="Storyboard1">
    
    		<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
    
    			<EasingColorKeyFrame KeyTime="0:0:0.5" Value="Yellow"/>
    
    		</ColorAnimationUsingKeyFrames>
    
    	</Storyboard>
    
    	<Storyboard x:Key="Storyboard2">
    
    		<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
    
    			<EasingColorKeyFrame KeyTime="0" Value="Yellow"/>
    
    			<EasingColorKeyFrame KeyTime="0:0:0.5" Value="#FF6B6B9B"/>
    
    		</ColorAnimationUsingKeyFrames>
    
    	</Storyboard>
    
    </ResourceDictionary>
    
    
    NonStoryboards.xaml里放有没有动画的内容,并保证Key一直
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    	<Storyboard x:Key="Storyboard1">
    
    	</Storyboard>
    
    	<Storyboard x:Key="Storyboard2">
    
    	</Storyboard>
    
    </ResourceDictionary>
    
    
    2.在App.xaml.cs增加一个静态方法,加载资源字典,定义在App中,好处是应用程序级别设置,而不是针对某个窗体
    public partial class App : Application {
    
    
    
    	protected override void OnStartup(StartupEventArgs e) {
    
    		base.OnStartup(e);
    
    		App.LoadResources(true);
    
    	}
    
    
    
    	public static void LoadResources(bool allowStoryboard) {
    
    		string resFilename = "/Res/" + (allowStoryboard ? "Storyboards.xaml" : "NonStoryboards.xaml");
    
    		ResourceDictionary resDic = new ResourceDictionary {
    
    			Source = new Uri(resFilename, UriKind.Relative)
    
    		};
    
    		Application.Current.Resources.MergedDictionaries.Clear();
    
    		Application.Current.Resources.MergedDictionaries.Add(resDic);
    
    	}
    
    }
    
    
    3.在窗体设置对象与对象的动画,以及动画效果的CheckBox开关
    这里要注意的是:Storyboard="{DynamicResource Storyboard1}必须使用DynamicResource(动态资源),如果使用了StaticResource则第一次加载后,不会更改。
    <Window
    
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="AnimationSwitch.MainWindow"
    
      Title="MainWindow" Height="350" Width="525">
    
    	<Window.Resources>
    
    	</Window.Resources>
    
    	<Window.Triggers>
    
    		<EventTrigger RoutedEvent="Mouse.MouseEnter" SourceName="rectangle">
    
    			<BeginStoryboard Storyboard="{DynamicResource Storyboard1}"/>
    
    		</EventTrigger>
    
    		<EventTrigger RoutedEvent="Mouse.MouseLeave" SourceName="rectangle">
    
    			<BeginStoryboard Storyboard="{DynamicResource Storyboard2}"/>
    
    		</EventTrigger>
    
    	</Window.Triggers>
    
     <Grid>
    
    		<Rectangle x:Name="rectangle" HorizontalAlignment="Left" Margin="79,43,0,0" Stroke="Black" Width="162" Fill="#FF6B6B9B" Height="99" VerticalAlignment="Top" RadiusY="22.5" RadiusX="22.5" d:LayoutOverrides="VerticalAlignment" />
    
    		<CheckBox Content="动画效果" HorizontalAlignment="Left" Margin="99,178,0,0" VerticalAlignment="Top" IsChecked="True" Width="80" Click="CheckBox_Click" />
    
     </Grid>
    
    </Window>
    
    
    
    
    CheckBox事件:
    public partial class MainWindow : Window {
    
    	public MainWindow() {
    
    		InitializeComponent();
    
    	}
    
    
    
    	private void CheckBox_Click(object sender, RoutedEventArgs e) {
    
    		CheckBox checkBox=sender as CheckBox;
    
    		App.LoadResources(checkBox.IsChecked.Value);
    
    	}
    
    
    
    }
    
    

    Sonny.Lin
    2011年6月8日 15:18

全部回复

  • 我个人认为这个是一个结构设计的问题,是没有一个很明确的答案的。不过我有一个很好的想法,你可以参考下:

     

    我们需要将所有的特效动画设计到一个资源字典中,然后我们还需要设计另外一套没有特效的,在运行时我们只需要控制加载哪套资源字典就可以实现不同的效果了,如果你要特效,就把特效资源加载到 Application.Current.Resources.MergedDictionaries 中去,否则就加载另一套。这一点就和加载不同的控件主题一样,我们可以在运行时切换所有的基本控件是否使用Win7的Aero主题还是切换使用经典主题。关于动态切换主题,你可以看看下面的链接:

    http://blog.xamltemplates.net/?p=20

     

    Sincerely,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年6月6日 8:45
    版主
  • 亲爱的Bob,You are great!
    根据你的提示,我已完成了动画全局开启与关闭。在此我介绍详细做法和代码。
    效果图:
    初始状态http://hi.csdn.net/attachment/201106/8/63407_1307546160YU7h.png
    鼠标移动到矩形上颜色更改http://hi.csdn.net/attachment/201106/8/63407_1307546160YU7h.png

    1.建立两个资源字典,分别为Storyboards.xaml和NonStoryboards.xaml
    Storyboards.xaml里放有动画的内容
    见项目文件截图:http://hi.csdn.net/attachment/201106/8/63407_1307546171UPyu.png

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    	<Storyboard x:Key="Storyboard1">
    
    		<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
    
    			<EasingColorKeyFrame KeyTime="0:0:0.5" Value="Yellow"/>
    
    		</ColorAnimationUsingKeyFrames>
    
    	</Storyboard>
    
    	<Storyboard x:Key="Storyboard2">
    
    		<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="rectangle">
    
    			<EasingColorKeyFrame KeyTime="0" Value="Yellow"/>
    
    			<EasingColorKeyFrame KeyTime="0:0:0.5" Value="#FF6B6B9B"/>
    
    		</ColorAnimationUsingKeyFrames>
    
    	</Storyboard>
    
    </ResourceDictionary>
    
    
    NonStoryboards.xaml里放有没有动画的内容,并保证Key一直
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    	<Storyboard x:Key="Storyboard1">
    
    	</Storyboard>
    
    	<Storyboard x:Key="Storyboard2">
    
    	</Storyboard>
    
    </ResourceDictionary>
    
    
    2.在App.xaml.cs增加一个静态方法,加载资源字典,定义在App中,好处是应用程序级别设置,而不是针对某个窗体
    public partial class App : Application {
    
    
    
    	protected override void OnStartup(StartupEventArgs e) {
    
    		base.OnStartup(e);
    
    		App.LoadResources(true);
    
    	}
    
    
    
    	public static void LoadResources(bool allowStoryboard) {
    
    		string resFilename = "/Res/" + (allowStoryboard ? "Storyboards.xaml" : "NonStoryboards.xaml");
    
    		ResourceDictionary resDic = new ResourceDictionary {
    
    			Source = new Uri(resFilename, UriKind.Relative)
    
    		};
    
    		Application.Current.Resources.MergedDictionaries.Clear();
    
    		Application.Current.Resources.MergedDictionaries.Add(resDic);
    
    	}
    
    }
    
    
    3.在窗体设置对象与对象的动画,以及动画效果的CheckBox开关
    这里要注意的是:Storyboard="{DynamicResource Storyboard1}必须使用DynamicResource(动态资源),如果使用了StaticResource则第一次加载后,不会更改。
    <Window
    
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="AnimationSwitch.MainWindow"
    
      Title="MainWindow" Height="350" Width="525">
    
    	<Window.Resources>
    
    	</Window.Resources>
    
    	<Window.Triggers>
    
    		<EventTrigger RoutedEvent="Mouse.MouseEnter" SourceName="rectangle">
    
    			<BeginStoryboard Storyboard="{DynamicResource Storyboard1}"/>
    
    		</EventTrigger>
    
    		<EventTrigger RoutedEvent="Mouse.MouseLeave" SourceName="rectangle">
    
    			<BeginStoryboard Storyboard="{DynamicResource Storyboard2}"/>
    
    		</EventTrigger>
    
    	</Window.Triggers>
    
     <Grid>
    
    		<Rectangle x:Name="rectangle" HorizontalAlignment="Left" Margin="79,43,0,0" Stroke="Black" Width="162" Fill="#FF6B6B9B" Height="99" VerticalAlignment="Top" RadiusY="22.5" RadiusX="22.5" d:LayoutOverrides="VerticalAlignment" />
    
    		<CheckBox Content="动画效果" HorizontalAlignment="Left" Margin="99,178,0,0" VerticalAlignment="Top" IsChecked="True" Width="80" Click="CheckBox_Click" />
    
     </Grid>
    
    </Window>
    
    
    
    
    CheckBox事件:
    public partial class MainWindow : Window {
    
    	public MainWindow() {
    
    		InitializeComponent();
    
    	}
    
    
    
    	private void CheckBox_Click(object sender, RoutedEventArgs e) {
    
    		CheckBox checkBox=sender as CheckBox;
    
    		App.LoadResources(checkBox.IsChecked.Value);
    
    	}
    
    
    
    }
    
    

    Sonny.Lin
    2011年6月8日 15:18
  • 非常详细 非常棒,标记为答案,可以造福后人了,哈哈


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年6月8日 15:28
    版主