{"id":3250,"date":"2015-07-13T18:41:55","date_gmt":"2015-07-13T18:41:55","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=3250"},"modified":"2015-07-13T18:41:55","modified_gmt":"2015-07-13T18:41:55","slug":"implementing-a-storyboard-in-code","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/implementing-a-storyboard-in-code\/","title":{"rendered":"Implementing a storyboard in code"},"content":{"rendered":"<p>So, I have a requirement to flash a cell (or row) in a XamDataGrid when an error occurs on the underlying model for the cell\/row. I&#8217;m currently implementing this in code simply because I&#8217;ve inherited a new control from the XamDataGrid to handle all my requirements.<\/p>\n<p>I won&#8217;t go into the full implementation of the style, but suffice to say the bit that matters looks like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar style = new Style(typeof (CellValuePresenter));\r\n\r\nvar trigger = new DataTrigger\r\n{\r\n   Binding = new Binding(&quot;DataItem.IsValid&quot;),\r\n   Value = false\r\n};\r\n\r\nvar animation = new BrushAnimation\r\n{\r\n   From = Brushes.LightPink,\r\n   To = Brushes.Firebrick,\r\n   Duration = TimeSpan.FromSeconds(0.2),\r\n   AutoReverse = true\r\n};\r\n\r\nvar storyboard = new Storyboard\r\n{\r\n   RepeatBehavior = RepeatBehavior.Forever\r\n};\r\n\r\nStoryboard.SetTargetProperty(animation, \r\n   new PropertyPath(BackgroundProperty));\r\nstoryboard.Children.Add(animation);\r\n\r\nvar enterBeginStoryboard = new BeginStoryboard\r\n{\r\n   Name = &quot;flashingStoryboard&quot;,\r\n   Storyboard = storyboard \r\n};\r\n\r\nstyle.RegisterName(&quot;flashingStoryboard&quot;, enterBeginStoryboard);\r\n\r\ntrigger.EnterActions.Add(enterBeginStoryboard);\r\ntrigger.ExitActions.Add(\r\n   new StopStoryboard \r\n   { \r\n      BeginStoryboardName = &quot;flashingStoryboard&quot; \r\n   });\r\n\r\nstyle.Triggers.Add(trigger);\r\n<\/pre>\n<p>In the above code we obviously create the style, with the target type of the CellValuePresenter. Then we&#8217;re using a trigger to detect when the view model&#8217;s IsValid property is false. This will cause our flashing animation\/storyboard to pulse the background brush from light pink to firebrick and back.<\/p>\n<p><em>Note: The BrushAnimation object is taken from a stackoverflow post <a href=\"http:\/\/stackoverflow.com\/questions\/8096852\/brush-to-brush-animation\" target=\"_blank\">Brush to Brush Animation<\/a><\/em><\/p>\n<p>The creation of the animation and storyboard, hopefully, are fairly self-explanatory. The idea is that when the trigger EnterActions is called the animation begins and when the ExitAction occurs the storyboard is stoppped. We need to supply a name to the StopStoryboard object and here&#8217;s where my first mistake was made.<\/p>\n<p>The line <em>style.RegisterName(&#8220;flashingStoryboard&#8221;, enterBeginStoryboard);<\/em> is important. Without it we will find that the named storyboard is not found by the StopStoryboard object. The storyboard needs to have the name registered within the<br \/>\nstyle&#8217;s namescope otherwise you&#8217;ll get the error I encountered which is an InvalidOperation exception<\/p>\n<p><em>&#8216;flashingStoryboard&#8217; name cannot be found in the name scope of &#8216;System.Windows.Style&#8217;<\/em><\/p>\n<p>This exception will only occur when the StopStoryboard code is called as this is the point it needs to find the object from the namescope.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So, I have a requirement to flash a cell (or row) in a XamDataGrid when an error occurs on the underlying model for the cell\/row. I&#8217;m currently implementing this in code simply because I&#8217;ve inherited a new control from the XamDataGrid to handle all my requirements. I won&#8217;t go into the full implementation of the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[13],"tags":[],"class_list":["post-3250","post","type-post","status-publish","format-standard","hentry","category-wpf"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/3250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=3250"}],"version-history":[{"count":2,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/3250\/revisions"}],"predecessor-version":[{"id":3252,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/3250\/revisions\/3252"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=3250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=3250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=3250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}