none
add animation to a custom comtrol RRS feed

  • 问题

  • my code:

    Generic.xaml:

                                                      

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:Controls="clr-namespace:EasyBill.CommonUI.Controls">
        <Style TargetType="{x:Type Controls:EasyAppButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Controls:EasyAppButton}">

                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">

                            <StackPanel Orientation="Vertical" RenderTransformOrigin="0.5,0.5">
                                <StackPanel.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform></ScaleTransform>
                                        <SkewTransform></SkewTransform>
                                        <RotateTransform></RotateTransform>
                                        <TranslateTransform></TranslateTransform>
                                    </TransformGroup>
                                </StackPanel.RenderTransform>
                                <Image x:Name="icon" Stretch="Uniform" Width="{TemplateBinding Controls:EasyAppButton.Width}" VerticalAlignment="Top">
                                    <Image.Triggers>
                                        <EventTrigger RoutedEvent="Image.MouseDown">
                                            <BeginStoryboard>
                                                <Storyboard x:Name="easing">
                                                    <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)" Storyboard.TargetName="icon">
                                                        <EasingPointKeyFrame KeyTime="0" Value="0.5,0.5"/>
                                                        <EasingPointKeyFrame KeyTime="0:0:0.3" Value="0.5,0.5"/>
                                                    </PointAnimationUsingKeyFrames>
                                                    <DoubleAnimation From="1.25" To="1" Duration="00:00:01" 
                         Storyboard.TargetName="myScaleTransform" 
                         Storyboard.TargetProperty="ScaleX">
                                                        <DoubleAnimation.EasingFunction>
                                                            <BackEase Amplitude="0"  EasingMode="EaseOut" />
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                    <DoubleAnimation From="1.25" To="1" Duration="00:00:01" 
                         Storyboard.TargetName="myScaleTransform" 
                         Storyboard.TargetProperty="ScaleY">
                                                        <DoubleAnimation.EasingFunction>
                                                            <BackEase Amplitude="0" EasingMode="EaseOut" />
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger>
                                    </Image.Triggers>
                                    <Image.RenderTransform>
                                        <ScaleTransform x:Name="myScaleTransform" />
                                    </Image.RenderTransform>
                                    <Image.Effect>
                                        <DropShadowEffect BlurRadius="7" ShadowDepth="4" Direction="315" Opacity="0.99"/>
                                    </Image.Effect>
                                </Image>
                                <TextBlock x:Name="content" Margin="0,2,0,0" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center">
                <TextBlock.Effect>
                    <DropShadowEffect/>
                </TextBlock.Effect>
                                </TextBlock>
                            </StackPanel>

                        </Border>
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="S_Enable">
                                <DoubleAnimation
    Storyboard.TargetName="icon"
                    Storyboard.TargetProperty="Opacity"
                    From="0.2" To="1"  Duration="0:0:0.3">
                                </DoubleAnimation>
                                <DoubleAnimation
                    Storyboard.TargetName="title"
                    Storyboard.TargetProperty="Opacity"
                    From="0.2" To="1"  Duration="0:0:0.3">
                                </DoubleAnimation>
                            </Storyboard>
                            <Storyboard x:Key="S_Disable">
                                <DoubleAnimation
    Storyboard.TargetName="icon"
                    Storyboard.TargetProperty="Opacity"
                    From="1" To="0.2"  Duration="0:0:0.3">
                                </DoubleAnimation>
                                <DoubleAnimation
                    Storyboard.TargetName="title"
                    Storyboard.TargetProperty="Opacity"
                    From="1" To="0.2"  Duration="0:0:0.3">
                                </DoubleAnimation>
                            </Storyboard>
                        </ControlTemplate.Resources>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>

    EasyAppButton.cs:

    namespace CommonUI.Controls
    {

        [TemplatePart(Name = ElementIcon, Type = typeof(Image))]
        [TemplatePart(Name = ElementEnable, Type = typeof(Storyboard))]
        [TemplatePart(Name = ElementDisable, Type = typeof(Storyboard))]

        public class EasyAppButton : ButtonBase
        {

            private const string ElementIcon = "icon";
            private const string ElementEnable = "S_Enable";
            private const string ElementDisable = "S_Disable";      

            Image IconTemplate = new Image();

    private string _Icon;
            public string Icon
            {
                get { return _Icon; }
                set { _Icon = value; }
            }

            static EasyAppButton()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(EasyAppButton), new FrameworkPropertyMetadata(typeof(EasyAppButton)));
                
            }

            public void Enable()
           {
                m_status = true;
                Storyboard m_enable = FindResource(ElementEnable) as Storyboard;
                if (null != m_enable)
                {
                    m_enable.Begin();
                }
           }

                

            public override void OnApplyTemplate()
            {

                base.OnApplyTemplate();
                IconTemplate = GetTemplateChild(ElementIcon) as Image;
                if (null != IconTemplate && _Icon!= String.Empty)
                {
                    IconTemplate.Source = new BitmapImage(new Uri(_Icon, UriKind.Absolute));
                }
            }

    }

    when I press F5 run this code,show error:

    System.InvalidOperationException was unhandled
      Message=No applicable name scope exists to resolve the name 'icon'.
      Source=PresentationFramework
      StackTrace:
           at System.Windows.Media.Animation.Storyboard.ResolveTargetName(String targetName, INameScope nameScope, DependencyObject element)
           at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
           at System.Windows.Media.Animation.Storyboard.ClockTreeWalkRecursive(Clock currentClock, DependencyObject containingObject, INameScope nameScope, DependencyObject parentObject, String parentObjectName, PropertyPath parentPropertyPath, HandoffBehavior handoffBehavior, HybridDictionary clockMappings, Int64 layer)
           at System.Windows.Media.Animation.Storyboard.BeginCommon(DependencyObject containingObject, INameScope nameScope, HandoffBehavior handoffBehavior, Boolean isControllable, Int64 layer)
           at System.Windows.Media.Animation.Storyboard.Begin()
           at EasyBill.CommonUI.Controls.EasyAppButton.Enable() in E:\Csharp\Controls\EasyAppButton.cs:line 76
           at EasyBill.CommonUI.Panels.EasyBreakPanel.ItemStatus(Int32 ThisItemID, String type) in E:\Csharp\EasyBill\EasyBill.CommonUI\Panels\EasyBreakPanel.cs:line 303
           at EasyBill.CommonUI.Panels.EasyBreakPanel.EasyBreakPanel_ClickClose(Object sender, RoutedEventArgs e) in E:\Csharp\EasyBill\EasyBill.CommonUI\Panels\EasyBreakPanel.cs:line 185
           at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
           at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
           at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
           at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
           at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
           at System.Windows.Input.InputManager.ProcessStagingArea()
           at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
           at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
           at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
           at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
           at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
           at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
           at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
           at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
           at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
           at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
           at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
           at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
           at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
           at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
           at System.Windows.Threading.Dispatcher.Run()
           at System.Windows.Application.RunDispatcher(Object ignore)
           at System.Windows.Application.RunInternal(Window window)
           at System.Windows.Application.Run(Window window)
           at System.Windows.Application.Run()
           at EasyBill.AppPlatform.App.Main() in E:\Csharp\obj\x86\Debug\App.g.cs:line 0
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException: 

    Thanks a lot



    2012年5月7日 6:21

答案

  • 原因在于你Storyboard.Begin 默认是对当前控件播放动画,但是当前控件的名字范围为你的Window了,而你的icon或者title是在你的控件的Template的这个名字范围内的,所以要报错。

    解决方法,让Template中一个元素去BeginStoryboard()既可。因为你的Storyboard包含对两个元素的动画,所以我建议你直接对这两个元素的共有父元素进行播放。比如如下:

      <Style TargetType="{x:Type local:EasyAppButton}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:EasyAppButton}">
              <Border Background="{TemplateBinding Background}"
                      BorderBrush="{TemplateBinding BorderBrush}"
                      BorderThickness="{TemplateBinding BorderThickness}" x:Name="outterBorder">
                      ...
                  <Image x:Name="icon" Stretch="Uniform" Width="{TemplateBinding local:EasyAppButton.Width}" VerticalAlignment="Top">
                    ...
                  </Image>
                    ...
              </Border>
              <ControlTemplate.Resources>
                <Storyboard x:Key="S_Enable">
                ...

    C#:

        public void Enable()
        {
          m_status = true;
          Storyboard m_enable = FindResource(ElementEnable) as Storyboard;
          Border outterBorder = GetTemplateChild("outterBorder") as Border;
          if (null != m_enable && null != outterBorder)
          {
            outterBorder.BeginStoryboard(m_enable);
          }
        }


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us

    2012年5月10日 9:25
    版主