<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SHAZAML! &#187; Trigger</title>
	<atom:link href="http://www.shazaml.com/archives/tag/trigger/feed" rel="self" type="application/rss+xml" />
	<link>http://www.shazaml.com</link>
	<description>The Blog for Design &#38; Development Superheroes</description>
	<lastBuildDate>Wed, 28 Jul 2010 21:02:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hidden Object: Episode 14 – Shake it up</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-14</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-14#comments</comments>
		<pubDate>Wed, 25 Nov 2009 13:05:17 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[ControlStoryboardAction]]></category>
		<category><![CDATA[EventTrigger]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[GlobalCounterMaxReachedTrigger]]></category>
		<category><![CDATA[IncrementGlobalCounterAction]]></category>
		<category><![CDATA[SetGlobalCounterAction]]></category>
		<category><![CDATA[Storyboard]]></category>
		<category><![CDATA[TimerTrigger]]></category>
		<category><![CDATA[Trigger]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=385</guid>
		<description><![CDATA[If the player clicks too many times within a 5 second time frame trying to find an item, play the shake animation.]]></description>
			<content:encoded><![CDATA[<p>So far in the game, we have particles when an item is clicked, a hint to show the location of an unfound item, but what should we do if the player goes berserk and wildly clicks all over the place in hopes of finding a difficult-to-find item? In this episode of <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">Creating a Hidden Object Game is Silverlight 3</a> we will add an earthquake effect if the player clicks too many times in a 5 second interval.</p>
<p>Let&#8217;s first start with the shake effect.  The magnifierCanvas Canvas contains the background image and all Paths for each clickable item. We will create a new storyboard called ShakeStoryboard that will animate the Left property of the Canvas:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec1.png" alt="" /></p>
<p> </p>
<p>Each of the 4 key frames set the Left property to a different value as shown in the storyboard XAML:</p>
<pre class="brush: xml; gutter: false;">
&lt;Storyboard x:Name=&quot;ShakeStoryboard&quot; RepeatBehavior=&quot;5x&quot; AutoReverse=&quot;False&quot; SpeedRatio=&quot;5&quot;&gt;
    &lt;DoubleAnimationUsingKeyFrames BeginTime=&quot;00:00:00&quot;
        Storyboard.TargetName=&quot;magnifierCanvas&quot;
        Storyboard.TargetProperty=&quot;(Canvas.Left)&quot;&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00&quot; Value=&quot;0&quot;/&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00.2000000&quot; Value=&quot;-10&quot;/&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00.4000000&quot; Value=&quot;10&quot;/&gt;
            &lt;EasingDoubleKeyFrame KeyTime=&quot;00:00:00.6000000&quot; Value=&quot;0&quot;/&gt;
    &lt;/DoubleAnimationUsingKeyFrames&gt;
&lt;/Storyboard&gt;
</pre>
<p> </p>
<p>The Storyboard has the RepeatBehavior property set to repeat 5 times and the SpeedRatio property set to speed up the animation.</p>
<p>If the player clicks on the background image 10 times within a 5 second interval, then the ShakeStoryboard will play. To accomplish this we need three SetGlobalCounterAction instances and one ControlStoryboardAction added to the UserControl:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec2.png" alt="" /></p>
<p>The first SetGlobalCounterAction sets the values for the TooManyClicks counter when the UserControl loads:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec3.png" alt="" /></p>
<p> </p>
<p>The ControlStoryboardAction plays the ShakeStoryboard when the GlobalCounterMaxReachedTrigger is fired for the TooManyClicks key which we set previously to 10.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec4.png" alt="" /></p>
<p>When the counter reaches 10 we need to set it back to zero which is what the second SetGlobalCounterAction does:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec5.png" alt="" /></p>
<p>The final SetGlobalCounterAction uses the TimerTrigger to reset the counter every 5 seconds:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec6.png" alt="" /></p>
<p> </p>
<p>The only thing left to do is add the IncrementGlobalCounterAction to the background image to increment the counter by 1:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/11/112509_1805_HiddenObjec7.png" alt="" /></p>
<p> </p>
<p>So with 5 Action instances, 3 Trigger types, 1 Storyboard, and 0 lines of code we were able to quickly add this feature to the game.</p>
<p><a href="http://www.shazaml.com/downloads/ClutteredCubeSource14.zip"><img class="alignnone size-full wp-image-319" title="Zip" src="http://www.shazaml.com/wp-content/uploads/2009/10/Zip.png" alt="Zip" width="93" height="96" /> Source Code</a></p>
<p><a href="http://www.shazaml.com/hidden-object-game-episode-14-demo"><img class="alignnone size-full wp-image-320" title="silverlight" src="http://www.shazaml.com/wp-content/uploads/2009/10/silverlight.png" alt="silverlight" width="93" height="96" /> Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-14/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Video: Creating a Silverlight 3 Casual Game using Blend 3 and Triggers, Actions, and Behaviors</title>
		<link>http://www.shazaml.com/archives/video-silverlight-casual-game</link>
		<comments>http://www.shazaml.com/archives/video-silverlight-casual-game#comments</comments>
		<pubDate>Mon, 09 Nov 2009 15:19:11 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[ChangePropertyAction]]></category>
		<category><![CDATA[ContinuousPlayMediaBehavior]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[GlobalCounterMinReachedTrigger]]></category>
		<category><![CDATA[GoToStateAction]]></category>
		<category><![CDATA[IncrementGlobalCounterAction]]></category>
		<category><![CDATA[InvokeCommandAction]]></category>
		<category><![CDATA[MagnifierOverBehavior]]></category>
		<category><![CDATA[MouseCursorBehavior]]></category>
		<category><![CDATA[ParticlesBehavior]]></category>
		<category><![CDATA[PlaySoundAction]]></category>
		<category><![CDATA[RemoveElementAction]]></category>
		<category><![CDATA[SetGlobalCounterAction]]></category>
		<category><![CDATA[SetInteractionPropertyAction]]></category>
		<category><![CDATA[ShowGlobalCounterBehavior]]></category>
		<category><![CDATA[Trigger]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[Visual State Manager]]></category>
		<category><![CDATA[VSM]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=333</guid>
		<description><![CDATA[Video presentation from Desert Code Camp 2009 - Silverlight 3 Casual Game]]></description>
			<content:encoded><![CDATA[<p>On Saturday, November 7, 2009 at 9:00am I presented at the Desert Code Camp in Phoenix, AZ. The topic of my presentation was Silverlight casual game development. In less than an hour I demonstrated how to use triggers, actions, and behaviors in Blend 3 to create a hidden object game. Because all code was contained in the TABs (Triggers, Actions, and Behaviors) there was no code behind for the main UserControl.</p>
<p>Here is a link to the <a title="Video - Creating a Silverlight 3 Casual Game using Blend 3 and Triggers, Actions, and Behaviors" href="http://www.shazaml.com/downloads/DesertCodeCamp2009-Silverlight3CasualGame.wmv">presentation video</a> in WMV format.</p>
<p>If you like you can see <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">all the episodes</a> and follow along with the tutorial.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/video-silverlight-casual-game/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
<enclosure url="http://www.shazaml.com/downloads/DesertCodeCamp2009-Silverlight3CasualGame.wmv" length="63294285" type="video/x-ms-wmv" />
		</item>
		<item>
		<title>Hidden Object: Episode 10 – Counting Items Found with Counter Triggers, Actions &amp; a Behavior</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-10</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-10#comments</comments>
		<pubDate>Sun, 04 Oct 2009 07:10:46 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[GlobalCounterChangedTrigger]]></category>
		<category><![CDATA[GlobalCounterMaxReachedTrigger]]></category>
		<category><![CDATA[GlobalCounterMinReachedTrigger]]></category>
		<category><![CDATA[GoToStateAction]]></category>
		<category><![CDATA[IncrementGlobalCounterAction]]></category>
		<category><![CDATA[SetGlobalCounterAction]]></category>
		<category><![CDATA[ShowGlobalCounterBehavior]]></category>
		<category><![CDATA[Trigger]]></category>
		<category><![CDATA[Visual State Manager]]></category>
		<category><![CDATA[VSM]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=267</guid>
		<description><![CDATA[Using a custom behavior, triggers, and actions we are able to count the number of items found and change state when the last item is found.]]></description>
			<content:encoded><![CDATA[<p>In episode 9 of <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">Creating a Hidden Object Game is Silverlight 3</a> we added additional screens to the game. In this episode, we will add the Win screen and a collection of triggers, actions, &amp; behaviors that work with a global counter.</p>
<p>The Win screen is shown after all 13 items have been clicked. What we need is an integer counter that subtracts one for each item clicked and when the count gets to zero change the state of the <em>MainPage</em> UserControl to show the screen.</p>
<p>Similar to what we did in the last episode, create a new Canvas called <em>winCanvas</em> and position it to the left of the UserControl on the artboard.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec1.png" alt="" /></p>
<p>In the States panel, add the WinScreen state to the ScreenStates group:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec2.png" alt="" /></p>
<p>With recording mode on for the WinScreen state, set the Top and Left properties of <em>winCanvas</em> to 0.</p>
<p>All we need to do is figure out a way to trigger a state change to show this screen.</p>
<p>The solution is a variation of the <a href="http://electricbeach.org/?p=349">Global State Behavior sample</a> by Christian Schormann which uses a <a href="http://msdn.microsoft.com/en-us/library/ms954629.aspx">Singleton</a> object containing a Dictionary to hold values based on a key (or tag).</p>
<p>Let&#8217;s go step-by-step through the use of the GlobalCounter classes before we look at any code.</p>
<p>The counter store (GlobalCounterStore) has an empty dictionary keyed using a CounterKey. Some trigger invokes SetGlobalCounterAction which sets the initial values for Value, MinValue, and MaxValue in a dictionary item with a CounterKey of &#8220;HiddenItems&#8221;. In this case the trigger that sets the values is an EventTrigger on the <em>MainPage</em> UserControl for the Loaded event:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec3.png"><img class="alignnone size-medium wp-image-253" title="100409_0710_HiddenObjec3.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec3-300x157.png" alt="100409_0710_HiddenObjec3.png" width="300" height="157" /></a> </p>
<p> </p>
<p>Any time that an entry is changed in the counter store, the Changed event is raised which passes Key, Value, MinValue, and MaxValue. Both the ShowGlobalCounterBehavior and the GlobalCounterChangedTrigger handle this event. Since every instance of the GlobalCounterChangedTrigger &amp; ShowGlobalCounterBehavior handle the Changed event they need to have a CounterKey property to determine if they should take any action for that event. In the case of ShowGlobalCounterBehavior, the associated TextBlock&#8217;s Text property is set to Value. For the GlobalCounterChangedTrigger any actions are invoked. In this episode, the GlobalCounterChangedTrigger is not used but is included for completeness.</p>
<p>Now that the counter store has been initialized with values, we can use the IncrementGlobalCounterAction to increment the value. In this case we are incrementing the value by -1 which updates the value in the counter store causing the Changed event to fire which is handled by the ShowGlobalCounterBehavior which sets the text on the TextBlock.</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec4.png"><img class="alignnone size-medium wp-image-254" title="100409_0710_HiddenObjec4.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec4-300x229.png" alt="100409_0710_HiddenObjec4.png" width="300" height="229" /></a></p>
<p> </p>
<p>The IncrementGlobalCounterAction is invoked for each Path object clicked until the counter reaches the MinValue:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec5.png"><img class="alignnone size-medium wp-image-255" title="100409_0710_HiddenObjec5.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec5-300x149.png" alt="100409_0710_HiddenObjec5.png" width="300" height="149" /></a></p>
<p> </p>
<p>The Changed event is fired to update the TextBlock, but the MinValueReached event is also fired. This is handled by the GlobalCounterMinReachedTrigger which compares its CounterKey with the Key passed in the event and if they match then the trigger invokes its actions. For this episode, there is a GoToStateAction associated with the UserControl that responds to the GlobalCounterMinReachedTrigger and sets the current state to WinScreen which shows <em>winCanvas</em>.</p>
<p>In cases where you want an incrementing counter instead of a decrementing one, pass a positive value for the IncrementCounterValueBy property of IncrementGlobalCounterAction and use the GlobalCounterMaxReachedTrigger.</p>
<p>The global counter classes can be used for many things including a lives counter, health, shield strength, or to keep track of a player&#8217;s score.</p>
<p>Here are a class diagram of the GlobalCounterStore and related classes:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec6.png" alt="" /></p>
<p>Besides the implementation of the Singleton pattern, the most interesting code can be found in the SaveToStore and IncrementCounter methods of GlobalCounterStore:</p>
<pre class="brush: csharp; gutter: false;">
internal sealed class GlobalCounterStore
{
    private Dictionary&lt;string, GlobalCounterItem&gt; store;

    internal void SaveToStore(string key, int value, int minValue, int maxValue)
    {
        if (key == null)
            return;
        var item = new GlobalCounterItem() {Value = value, MinValue = minValue, MaxValue = maxValue };

        if (store.ContainsKey(key))
        {
            store[key] = item;
        }
        else
        {
            store.Add(key, item);
        }

        OnChanged(key, item);
    }

    internal void IncrementCounter(string key, int incrementBy)
    {
        if ((key == null) || !store.ContainsKey(key))
            return;

        int newValue = store[key].Value + incrementBy;
        store[key].Value = newValue;

        OnChanged(key, store[key]);

        if (newValue &gt;= store[key].MaxValue)
            OnMaxValueReached(key, store[key]);

        if (newValue &lt;= store[key].MinValue)
            OnMinValueReached(key, store[key]);
    }
}
</pre>
<p> </p>
<p>The SetGlobalCounterAction is a TriggerAction that defines four dependency properties for CounterKey, CounterValue, CounterMinValue, and CounterMaxValue. The Invoke method calls the SaveToStore method on GlobalCounterStore.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec7.png" alt="" /></p>
<p>The IncrementGlobalCounterAction is a TargetedTriggerAction that defines dependency properties for CounterKey and IncrementCounterValueBy. It&#8217;s Invoke method calls the IncrementCounter method on GlobalCounterStore.</p>
<p> </p>
<p>The three triggers are very similar in that each defines a CounterKey dependency property and each adds a handler to an event raised by GlobalCounterStore:</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/10/GlobalCounterTriggers.png"><img class="alignnone size-full wp-image-268" title="GlobalCounterTriggers" src="http://www.shazaml.com/wp-content/uploads/2009/10/GlobalCounterTriggers.png" alt="GlobalCounterTriggers" width="266" height="679" /></a></p>
<p> </p>
<p>In the case of GlobalCounterMinReachedTrigger, the OnAttached method adds a handler for the GlobalCounterStore&#8217;s MinValueReached event whereas the handler is removed in the OnDetaching method:</p>
<pre class="brush: csharp; gutter: false;">
public class GlobalCounterMinReachedTrigger : TriggerBase&lt;DependencyObject&gt;
{
    protected override void OnAttached()
    {
        base.OnAttached();
        GlobalCounterStore.Instance.MinValueReached += Instance_MinValueReached;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        GlobalCounterStore.Instance.MinValueReached -= Instance_MinValueReached;
    }

    void Instance_MinValueReached(object sender, GlobalCounterEventArgs e)
    {
        if (CounterKey == null)
            return;

        if (CounterKey == e.Key)
            this.InvokeActions(e);
    }
}
</pre>
<p> </p>
<p>When the MinValueReached event is raised due to a change in the GlobalCounterStore to any dictionary entry regardless of its key, the passed key (e.Key) is compared to the CounterKey property. If the values match, then the actions for this trigger are invoked.</p>
<p> </p>
<p>ShowGlobalCounterBehavior is a behavior that can be attached to a TextBlock control and functions is a similar way as the triggers:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec9.png" alt="" /></p>
<p> </p>
<p>It defines the CounterKey property and handles the Changed event raised by GlobalCounterKey:</p>
<pre class="brush: csharp; gutter: false;">
public class ShowGlobalCounterBehavior : Behavior&lt;TextBlock&gt;
{
    protected override void OnAttached()
    {
        base.OnAttached();
        GlobalCounterStore.Instance.Changed += Instance_Changed;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        GlobalCounterStore.Instance.Changed -= Instance_Changed;
    }
 
    void Instance_Changed(object sender, GlobalCounterEventArgs e)
    {
        if (CounterKey == e.Key)
        {
            if (e.Value &gt; e.MaxValue)
                AssociatedObject.Text = e.MaxValue.ToString();
            else if (e.Value &lt; e.MinValue)
                AssociatedObject.Text = e.MinValue.ToString();
            else
                AssociatedObject.Text = e.Value.ToString();
        }
    }
}
</pre>
<p> </p>
<p>It is possible to increment the Value in the counter store by more than 1 so I added checks so that the TextBlock will never show values greater than MaxValue or less than MinValue.</p>
<p> </p>
<p>Now it is time to use these classes in Blend. Drop an instance of SetGlobalCounterAction on the UserControl, a GoToStateAction on LayoutRoot, and a IncrementGlobalCounterAction on a Path:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec10.png" alt="" /></p>
<p> </p>
<p>The values for SetGlobalCounterAction are set as follows:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec11.png" alt="" /></p>
<p> </p>
<p>The new GoToStateAction uses GlobalCounterMinReachedTrigger and sets the StateName to WinScreen:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec12.png" alt="" /></p>
<p> </p>
<p>Each path will have an IncrementGlobalCounterAction set with these values:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec13.png" alt="" /></p>
<p> </p>
<p> </p>
<p>Finally, we add a TextBlock to our Canvas to hold the count of remaining items and add the ShowGlobalCounterBehavior to it:</p>
<p> </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec14.png" alt="" /></p>
<p> </p>
<p> <a href="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec15.png"><img class="alignnone size-medium wp-image-265" title="100409_0710_HiddenObjec15.png" src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec15-300x156.png" alt="100409_0710_HiddenObjec15.png" width="300" height="156" /></a></p>
<p> </p>
<p> </p>
<p>The only property to set on the behavior is the CounterKey: </p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/10/100409_0710_HiddenObjec16.png" alt="" /></p>
<p> </p>
<p> </p>
<p>Once we add IncrementGlobalCounterAction to each Path, we can run the game and as we find items the counter will decrement by 1. When the value reaches 0, then the winning screen is shown.</p>
<p> </p>
<p><a href="http://www.shazaml.com/downloads/ClutteredCubeSource10.zip">Source code</a></p>
<p><a href="http://www.shazaml.com/hidden-object-episode-10-demo">Demo</a></p>
<p> </p>
<p>In the <a href=" http://www.shazaml.com/archives/hidden-object-episode-11 ">next episode</a> we will update the Particles Behavior to allow particle custom shapes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-10/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hidden Object: Episode 7 – Use an Action to Toggle the Magnifier Behavior</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-7</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-7#comments</comments>
		<pubDate>Sat, 26 Sep 2009 13:03:42 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[BaseBehavior]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[MagnifierOverBehavior]]></category>
		<category><![CDATA[SetInteractionPropertyAction]]></category>
		<category><![CDATA[Trigger]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=186</guid>
		<description><![CDATA[Using the magnifier-styled CheckBox from the last episode along with the Behavior base classes and SetInteractionPropertyAction we finish the magnification feature.]]></description>
			<content:encoded><![CDATA[<p>This is episode 7 of <a href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">Creating a Hidden Object Game is Silverlight 3</a>.</p>
<p>In the last few posts we have been working on the magnifier feature of the game which we will finish in this episode.</p>
<p>Please review the following posts:</p>
<ul>
<li><a href="http://www.shazaml.com/archives/hidden-object-episode-5">Episode 5 – Add a Magnifier Behavior</a></li>
<li><a href="http://www.shazaml.com/archives/base-classes-for-custom-behaviors">Base Classes for Custom Behaviors</a></li>
<li><a href="http://www.shazaml.com/archives/setinteractionpropertyaction">Creating an Action to set Properties on Actions &amp; Behaviors</a></li>
<li><a href="http://www.shazaml.com/archives/hidden-object-episode-6">Episode 6 – Create a CheckBox from an Image</a></li>
</ul>
<p>First we will add in the following files into the ClutteredCube project:</p>
<ul>
<li>
<div>Interactivity folder (from <a href="http://www.shazaml.com/archives/base-classes-for-custom-behaviors">Base Classes for Custom Behaviors</a>)</div>
<ul>
<li>BaseBehavior.cs</li>
<li>BaseBehaviorT.cs</li>
</ul>
</li>
<li>
<div>Interactivity\SetInteractionPropertyAction folder (from <a href="http://www.shazaml.com/archives/setinteractionpropertyaction">Creating an Action to set Properties on Actions &amp; Behaviors</a>)</div>
<ul>
<li>ConverterHelper.cs</li>
<li>SetInteractionPropertyAction.cs</li>
</ul>
</li>
</ul>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092609_1303_HiddenObjec1.png" alt="" /></p>
<p>The first thing we want to do is to change MagnifierOverBehavior so that it inherits from our custom behavior base class thus inheriting the IsEnabled property:</p>
<pre class="brush: csharp; light: true;">
public class MagnifierOverBehavior : BaseBehavior&lt;FrameworkElement&gt;
</pre>
<p>The only other change we need to make this behavior is not set the Effect property on MouseEnter but instead in MouseMove based on the value of the IsEnabled property:</p>
<pre class="brush: csharp; light: true;">
private void AssociatedObject_MouseEnter( object sender, MouseEventArgs e )
{
  this.AssociatedObject.MouseMove += new MouseEventHandler( AssociatedObject_MouseMove );
  //this.AssociatedObject.Effect = this.magnifier;
}

private void AssociatedObject_MouseMove( object sender, MouseEventArgs e )
{
  if (IsEnabled)
  {
    if (this.AssociatedObject.Effect != this.magnifier)
    {
      this.AssociatedObject.Effect = this.magnifier;
    }
    ...
  }
}
</pre>
<p>In Blend, open the MainPage and select the MagnifierOverBehavior in the Object tree under <em>magnifierCanvas</em>. Name the behavior <em>magnifierBehavior</em> and set IsEnabled to false:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092609_1303_HiddenObjec2.png" alt="" /></p>
<p>From the Assets tab drag two instances of SetInteractionPropertyAction onto the CheckBox magnifier control:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092609_1303_HiddenObjec3.png" alt="" /></p>
<p>On the first one, set the properties as follows:</p>
<ul>
<li>EventName: Checked</li>
<li>TargetName: magnifierCanvas</li>
<li>ObjectName: magnifierBehavior</li>
<li>PropertyName: IsEnabled</li>
<li>Value: true</li>
</ul>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092609_1303_HiddenObjec4.png" alt="" /></p>
<p>Set the second the same as the first, except:</p>
<ul>
<li>EventName: Unchecked</li>
<li>Value: false</li>
</ul>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092609_1303_HiddenObjec5.png" alt="" /></p>
<p>Make sure that the CheckBox control IsChecked property is false to match the InEnabled value of false for <em>magniferBehavior</em>.</p>
<p>Run the game and verify that magnification is only turned on when the CheckBox is checked.</p>
<p>Let&#8217;s do one more thing to finish this episode. Notice that magnifier.png has a white background behind the glass part of the magnifying glass. The image should be on top of something white like a notepad. Import the notepad image and drop it at the bottom of LayoutRoot.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/notepad.png" alt="notepad" /></p>
<p>Position it how you want it and move the magnifier CheckBox on top of it.</p>
<p><a href="http://www.shazaml.com/downloads/ClutteredCubeSource7.zip">Source Code</a></p>
<p><a href="http://www.shazaml.com/hidden-object-episode-7-demo">Demo</a></p>
<p>There are many features to add so I will keep the <a href="http://www.shazaml.com/archives/hidden-object-episode-8">next episode</a> contents a surprise.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-7/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating an Action to set Properties on Actions &amp; Behaviors</title>
		<link>http://www.shazaml.com/archives/setinteractionpropertyaction</link>
		<comments>http://www.shazaml.com/archives/setinteractionpropertyaction#comments</comments>
		<pubDate>Tue, 22 Sep 2009 23:36:06 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Action]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[ChangePropertyAction]]></category>
		<category><![CDATA[SetInteractionPropertyAction]]></category>
		<category><![CDATA[ShowMessageBox]]></category>
		<category><![CDATA[Trigger]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=137</guid>
		<description><![CDATA[The SetInteractionPropertyAction allows you to set properties on Actions and Behaviors as a result of a Trigger.]]></description>
			<content:encoded><![CDATA[<p>Behaviors and actions have properties of their own and it would be useful to be able to set those properties as a result of a trigger.</p>
<p>For this post, we will use the ShowMessageBox action that is part of the <a href="http://expressionblend.codeplex.com/">Expression Blend Samples</a> CodePlex project.</p>
<p>To explore this, create a Silverlight project in Blend 3, drop a Rectangle on LayoutRoot, and drop a ShowMessageBox action onto the Rectangle. The ShowMessageBox action is under the Behaviors &gt; Experimental in the Assets tab:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA1.png" alt="" /></p>
<p>Change the rectangle stroke and fill so that it is easily seen.</p>
<p>Set the Caption and Message properties of ShowMessageBox:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA2.png" alt="" /></p>
<p>When we run the application and click on the rectangle, the message box shows:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA3.png" alt="" /></p>
<p>What if we wanted to change the value of the Message property when a CheckBox control is checked or unchecked?</p>
<p>To accomplish this, we will create SetInteractionPropertyAction that derives from TargetedTriggerAction and adds properties for the name of the action or behavior, the property on that action/behavior, and the value to set on that property:</p>
<pre class="brush: csharp; gutter: false;">
public string ObjectName
{
  get { return (string)GetValue(ObjectNameProperty); }
  set { SetValue(ObjectNameProperty, value); }
}
public static readonly DependencyProperty ObjectNameProperty =
  DependencyProperty.Register(&quot;ObjectName&quot;,
  typeof(string), typeof(SetInteractionPropertyAction),
  new PropertyMetadata(null));&lt;/pre&gt;

public string PropertyName
{
  get { return (string)base.GetValue(PropertyNameProperty); }
  set { base.SetValue(PropertyNameProperty, value); }
}
public static readonly DependencyProperty PropertyNameProperty =
    DependencyProperty.Register(&quot;PropertyName&quot;,
    typeof(string), typeof(SetInteractionPropertyAction),
    new PropertyMetadata(null));

public string Value
{
  get { return (string)base.GetValue(ValueProperty); }
  set { base.SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
  DependencyProperty.Register(&quot;Value&quot;,
  typeof(string), typeof(SetInteractionPropertyAction),
  new PropertyMetadata(null));
</pre>
<p>Next we need to implement the Invoke method which finds the action or behavior under the Target control that matches the ObjectName and sets its property defined by PropertyName to the value specified in Value.</p>
<p>To find actions and behaviors associated with a given object, we use the GetTriggers and GetBehaviors static methods defined on the Interaction class in the System.Windows.Interactivity namespace:</p>
<pre class="brush: csharp; light: true;">
  public static TriggerCollection GetTriggers(DependencyObject obj);
  public static BehaviorCollection GetBehaviors(DependencyObject obj);
</pre>
<p>If we look at some sample XAML we can see that when an action is defined, it becomes part of the Triggers collection and appears under the trigger that causes the action to be invoked. If multiple actions are associated with the same object and use the same trigger, the actions appear together:</p>
<pre class="brush: xml; light: true;">
&lt;Path&gt;
  &lt;i:Interaction.Triggers&gt;
    &lt;i:EventTrigger EventName=&quot;MouseLeftButtonDown&quot;&gt;
      &lt;ic:ChangePropertyAction x:Name=&quot;changeProperty&quot; TargetName=&quot;staplerText&quot; PropertyName=&quot;Opacity&quot; Value=&quot;0.4&quot;/&gt;
      &lt;im:PlaySoundAction x:Name=&quot;playSoundAction&quot; Source=&quot;/Audio/magic_wand.mp3&quot;/&gt;
      &lt;ic:RemoveElementAction x:Name=&quot;removeElement&quot; /&gt;
    &lt;/i:EventTrigger&gt;
  &lt;/i:Interaction.Triggers&gt;
&lt;/Path&gt;
</pre>
<p>Calling Interaction.GetTriggers passing a reference to the hosting Path, will return a single trigger of type EventTrigger. For that trigger, we can use its Actions property to access the three actions.</p>
<p>If we look at some XAML for a behavior, we notice that there is a Behaviors collection containing one or more behaviors and for each behavior there is an optional Triggers collection:</p>
<pre class="brush: xml; light: true;">
&lt;Canvas&gt;
  &lt;i:Interaction.Behaviors&gt;
    &lt;local:ParticlesBehavior x:Name=&quot;particles&quot;&gt;
      &lt;i:Interaction.Triggers&gt;
        &lt;i:EventTrigger SourceName=&quot;staplerPath&quot; EventName=&quot;MouseLeftButtonDown&quot;&gt;
          &lt;i:InvokeCommandAction CommandName=&quot;ShowParticles&quot;/&gt;
        &lt;/i:EventTrigger&gt;
        &lt;i:EventTrigger SourceName=&quot;idolPath&quot; EventName=&quot;MouseLeftButtonDown&quot;&gt;
          &lt;i:InvokeCommandAction CommandName=&quot;ShowParticles&quot;/&gt;
        &lt;/i:EventTrigger&gt;
      &lt;/i:Interaction.Triggers&gt;
    &lt;/local:ParticlesBehavior&gt;

    &lt;Behaviors:MagnifierOverBehavior x:Name=&quot;magnifier&quot;/&gt;
  &lt;/i:Interaction.Behaviors&gt;
&lt;/Canvas&gt;
</pre>
<p>In the case, calling Interaction.GetBehaviors with a reference to the Canvas will return two behaviors: ParticlesBehavior and MagnifierOverBehavior</p>
<p>Just like any object you add to the Object tree, you can set the name of an action or behavior. This adds an x:Name property in the XAML and the name appears in the name textbox in the Properties panel. To access the x:Name property in code, get a reference to the behavior or action and call GetValue passing the FrameworkElement.NameProperty dependency property:</p>
<pre class="brush: csharp; light: true;">
  string actionName = (string)action.GetValue(FrameworkElement.NameProperty);
  string behaviorName = (string)behavior.GetValue(FrameworkElement.NameProperty);
</pre>
<p>For SetInteractionPropertyAction we define the following methods that will try to find an action or behavior that matches the same name as the ObjectName property:</p>
<pre class="brush: csharp; light: true;">
private object TryFindBehavior()
{
  var behaviors = Interaction.GetBehaviors(Target);

  foreach (Behavior behavior in behaviors)
  {
    string behaviorName = (string)behavior.GetValue(FrameworkElement.NameProperty);

    if (behaviorName == ObjectName)
    {
      return behavior;
    }
  }

return null;
}

private object TryFindAction()
{
  var triggers = Interaction.GetTriggers(Target);

  foreach (System.Windows.Interactivity.TriggerBase trigger in triggers)
  {
    foreach (System.Windows.Interactivity.TriggerAction action in trigger.Actions)
    {
      string actionName = (string)action.GetValue(FrameworkElement.NameProperty);

      if (actionName == ObjectName)
      {
        return action;
      }
    }
  }

return null;
}
</pre>
<p>Finally, the Invoke method uses the previous two methods to find a matching action or behavior and to set one of its properties. I admit that a large portion of the Invoke method in the full project source code was borrowed from the SetProperty action defined in the Expression.Samples.Interactivity assembly (thanks .NET Reflector) :</p>
<pre class="brush: csharp; light: true;">
Type itemType = null;
object item = null;

item = TryFindBehavior();

if (item == null)
{
  item = TryFindAction();
}

if (item == null)
{
  return;
}
else
{
  itemType = item.GetType();
}

PropertyInfo property = itemType.GetProperty(this.PropertyName);
property.SetValue(item, this.Value, null);
</pre>
<p>After compiling the code, the SetInteractionPropertyAction will appear in the Assets panel.</p>
<p>Let&#8217;s add a CheckBox control to LayoutRoot and drop two instances of SetInteractionPropertyAction onto the CheckBox. Next select the ShowMessageBox action and set its name property to <em>showMessageBox</em>.</p>
<p>Click on the first instance of SetInteractionPropertyAction and set it&#8217;s EventName, TargetName, ObjectName, PropertyName, and Value properties:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA4.png" alt="" /></p>
<p>For the second instance of SetInteractionPropertyAction, set the same properties as follows:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA5.png" alt="" /></p>
<p>Now run the application. Initially, when you click on the rectangle, you will see a message box that says &#8220;Hello World&#8221;.</p>
<p>When you click on the CheckBox and then click the rectangle, the message will change to &#8220;I am checked&#8221;. Unchecking the CheckBox and clicking on the rectangle will cause the message to change to &#8220;I am unchecked&#8221;.</p>
<p><div id="silverlightControlHost"><object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="200" height="100"><param name="source" value="http://www.shazaml.com/SL/SetInteractionProperty.xap"/><param name="background" value="white" /><param name="minRuntimeVersion" value="3.0.40723.0" /><param name="autoupgrade" value="true" /><param name="enableHtmlAccess" value="true" /><a href="http://go.microsoft.com/fwlink/?LinkID=149156" style="text-decoration: none;"><img src="http://storage.timheuer.com/sl4wp-ph.png" alt="Install Microsoft Silverlight" style="border-style: none; width:400px; height:200px"/></a></object><iframe style="visibility:hidden;height:0;width:0;border:0px" id="_sl_historyFrame"></iframe></div><br /></p>
<p> </p>
<p>We have successfully set the property of one action based on a trigger invoking SetInteractionPropertyAction.</p>
<p>If you look at the Common Properties group for our custom action, you will notice that the editors for ObjectName, PropertyName, and Value are just TextBox controls. I would like the design-time experience to be better for this action. Maybe in a future post, this will be revisited. You might have noticed that the Value property is of type string even though the data type of the property that corresponds to PropertyName might be another data type. I originally had Value as type object, but there were times when the textbox would gray out and not allow any input. This would also be solved if custom property editors were defined.</p>
<p>The Microsoft.Expression.Interactions assembly defines an action called ChangePropertyAction that sets the property on an object and has a much better designer experience. It provides a drop-down containing property names and when a property is selected, the editor for the Value reflects the underlying data type of the property:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA7.png" alt="" /></p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/092209_2335_CreatinganA8.png" alt="" /></p>
<p>I would like to include these editors plus one that would show a list of named actions and behaviors for the given Target grouped in the list under the words: Actions or Behaviors.</p>
<p><a href="http://www.shazaml.com/downloads/SetInteractionProperty.zip">Source code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/setinteractionpropertyaction/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hidden Object: Episode 4 – Adding Particles with a Behavior</title>
		<link>http://www.shazaml.com/archives/hidden-object-episode-4</link>
		<comments>http://www.shazaml.com/archives/hidden-object-episode-4#comments</comments>
		<pubDate>Fri, 18 Sep 2009 03:25:53 +0000</pubDate>
		<dc:creator>Mark Tucker</dc:creator>
				<category><![CDATA[Hidden Object Game]]></category>
		<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Behavior]]></category>
		<category><![CDATA[Blend]]></category>
		<category><![CDATA[DebugEventTrigger]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[InvokeCommandAction]]></category>
		<category><![CDATA[ParticlesBehavior]]></category>
		<category><![CDATA[RemoveElementAction]]></category>
		<category><![CDATA[Trigger]]></category>

		<guid isPermaLink="false">http://www.shazaml.com/?p=80</guid>
		<description><![CDATA[Create ParticlesBehavior and make use of DebugEventTrigger, InvokeCommandAction, and RemoveElementAction]]></description>
			<content:encoded><![CDATA[<p>In the previous episodes of <a title="Creating a Hidden Object Game in Silverlight 3" href="http://www.shazaml.com/archives/creating-a-hidden-object-game-in-silverlight-3">Creating a Hidden Object Game in Silverlight 3</a> we spent all of our time in Blend. Now we are going to put on our developer hat and create our own custom behavior that will shoot particles when an item is clicked. This will give a nice visual effect that compliments marking the item off the list and the sound effect.</p>
<p>Click <a href="http://www.shazaml.com/hidden-object-episode-4-demo">here</a> to see a demo of what the game will look like after we finish this episode.</p>
<p>I want to make sure that I give tons of credit to Robby Ingebretsen from <a href="http://blog.nerdplusart.com/">nerdplusart</a> for his <a href="http://blog.nerdplusart.com/archives/silverlight-particle-generator">Silverlight Particle Generator</a>. If you haven&#8217;t had a chance to play with it before (and I do mean play) then take a few minutes to do so.</p>
<p><a href="http://labs.nerdplusart.com/particles/fullscreen.php"><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec1.png" border="0" alt="" /></a></p>
<p>The plan is to take the ParticleControl from that solution and wrap it in a ParticlesBehavior that will be triggered when the item&#8217;s path (ex: staplerPath) is clicked.</p>
<p>First we need to take a side-step into the differences between an action and a behavior and their relationship to triggers. We will start to see some patterns emerge. In the previous episodes we looked at two actions (ChangeProperyAction &amp; PlaySoundAction) and noticed that an action specifies what will happen and to which object. When the action will occur is specified by a trigger. There are two main types of actions (TriggerAction &amp; TargetedTriggerAction). The first allows us to attach to an object and invoke some code when a trigger is fired whereas the second does that <em>and</em> defines a target for the action that is different from the object that the action is associated with. Both of these actions can only be called by a single trigger. A behavior in some ways appears simpler than an action because there is no direct connection to a trigger and therefore no <em>Invoke</em> method to be called. All we get are overrides for OnAttached and OnDetaching. But behaviors are powerful, can hold state, and can do various things based on <em>many</em> triggers.</p>
<p>For a class diagram of the Action and Behavior base classes as well as some great sample behaviors, check out the <a href="http://www.silverlightshow.net/items/Behaviors-and-Triggers-in-Silverlight-3.aspx">Behaviors and Triggers in Silverlight 3</a> article on SilverlightShow.</p>
<p>Hint: We will use the MagnifierOverBehavior in the next episode.</p>
<p>Enough talking lets open Blend and get coding. In the Projects panel, create a folder called Interactivity and under it a folder called ParticlesBehavior. Interactivity seems to be the term Microsoft uses to talk about both actions and behaviors and by the time we are done with this tutorial we will have created both types. I am doing this in Blend, because it has a template to create a basic behavior.</p>
<p>Right-click the ParticlesBehavior folder, pick Add New Item, select Behavior, and enter the name: ParticlesBehavior.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec2.png" alt="" /></p>
<p>Click OK to create the behavior.</p>
<p>After saving all the files, open the solution concurrently in Visual Studio 2008 so that you can switch back and forth between Visual Studio and Blend as needed.</p>
<p>Go to the <a href="http://blog.nerdplusart.com/archives/silverlight-particle-generator">Silverlight Particle Generator</a> page and download the source code. Copy the following files into the Interactivity\ParticlesBehavior folder and include them in the project:</p>
<ul style="margin-left: 38pt">
<li>ParticleControl.xaml</li>
<li>ParticleControl.xaml.cs</li>
<li>LICENSE.TXT</li>
</ul>
<p>The quick idea behind the ParticlesBehavior is that it will be attached to the LayoutRoot canvas. The behavior will handle the canvas&#8217;s MouseMove event and store the current mouse position. When the ParticlesBehavior is notified that it should show particles, it creates an instance of the ParticleControl and positions it by setting the OffsetX and OffsetY properties.</p>
<p>We start by changing the class declaration so that ParticlesBehavior inherits from Behavior&lt;Canvas&gt;. Now throughout code, AssociatedObject will be of type Canvas. This also means that this behavior can only be attached to objects of type Canvas. In the OnAttached method an event handler is created for the canvas&#8217; MouseMove event whereas in the OnDetaching method the event handler is removed. When the mouse is moved, the current position is recorded.</p>
<pre class="brush: csharp; gutter: false;">
public class ParticlesBehavior : Behavior&lt;Canvas&gt;
{
private Point currentMousePosition;

protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseMove += new MouseEventHandler(AssociatedObject_MouseMove);
}

protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseMove -= new MouseEventHandler(AssociatedObject_MouseMove);
}

void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
{
currentMousePosition = e.GetPosition(null);
}
}
</pre>
<p>Now we need a way to trigger when the control will be shown or hidden. This is achieved by adding a command to ParticlesBehavior called ShowParticles. In the constructor, instantiate a new ActionCommand and pass it an Action delegate. The method that you use can have no parameters or one parameter (of type object). Later when triggers are associated with this behavior you can set the value of the CommandParameter. If you have a method that passes an object parameter, you can get access to the parameter.</p>
<p>This command then creates and sets properties on the ParticleControl and adds it to the Children collection of LayoutRoot. Update the ParticlesBehavior class to include this code:</p>
<pre class="brush: csharp; gutter: false; highlight: [5,6,7,8,27,28,29,30,31,33,34,35,36,37,38,39,40,41];">
public class ParticlesBehavior : Behavior&lt;Canvas&gt;
{
    private Point currentMousePosition;

    public ParticlesBehavior()
    {
        this.ShowParticles = new ActionCommand(this.OnShowParticles);
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.MouseMove += new MouseEventHandler(AssociatedObject_MouseMove);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.MouseMove -= new MouseEventHandler(AssociatedObject_MouseMove);
    }

    void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
    {
        currentMousePosition = e.GetPosition(null);
    }

    public ICommand ShowParticles
    {
        get;
        private set;
    }

    private void OnShowParticles()
    {
        ParticleControl p = new ParticleControl();

        p.OffsetX = currentMousePosition.X;
        p.OffsetY = currentMousePosition.Y;

        AssociatedObject.Children.Add(p);
    }

}
</pre>
<p>If you compile the project, you will now see the ParticlesBehavior in the Assets panel. Drag and drop it on LayoutRoot. The properties panel will have a ShowParticles group created for the ShowParticles Command and an empty Triggers list:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec3.png" alt="" /></p>
<p>Click the plus sign to the right of Triggers and pick EventTrigger and set the SourceName (staplerPath) and EventName (MouseLeftButtonDown):</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec4.png" alt="" /></p>
<p>What this is saying is that when the staplerPath object is clicked then it will call the ShowParticles command on this behavior. You could also specify a CommandParameter which you then could use if OnShowParticles had an object parameter defined. When you click the plus sign next to Triggers again, you can specify another EventTrigger to be called when idolPath is clicked. Repeat this for all the paths.</p>
<p>Run the game now and click on an item. You should see lots of particles flowing from that location. Find another object and click it and there will be a second stream of particles. The ParticleControl currently doesn&#8217;t have a way to stop the particles from flowing. We will take care of that in a minute. But let&#8217;s first try to figure out what is happening between the triggers and the behavior. The command defined on the behavior is an ICommand, it knows nothing about triggers. And triggers just know when something is going to happen. How does it know to call a command on the behavior? The answer is the InvokeCommandAction that is created behind the scenes. This can be seen in a diagram from the Expression Blend SDK User Guide:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec5.png" alt="" /></p>
<p>It might be a good learning opportunity to intercept the trigger before it calls InvokeCommandAction and see it doing the work of connecting the trigger to the behavior. Let&#8217;s create a trigger that we can use and debug. In a new folder under Interactivity called DebugEventTrigger, create a class called DebugEventTrigger.cs:</p>
<pre class="brush: csharp; gutter: false;">
public class DebugEventTrigger : System.Windows.Interactivity.EventTrigger
{
    public DebugEventTrigger() : base() {}

    public DebugEventTrigger(string eventName) : base(eventName) {}

    protected override void OnEvent(EventArgs eventArgs)
    {
        base.OnEvent(eventArgs);
    }
}
</pre>
<p>We derive the class from EventTrigger so we can use it just list the triggers we have already used. Compile the project and in Blend, add this trigger to the triggers collection on the ParticlesBehavior and select the SourceName and EventName. Switch back to Visual Studio and set a breakpoint in the OnEvent method. Run the app in debug mode from Visual Studio. When the breakpoint is hit, look at the Locals window and you will see that the trigger has a single action, InvokeCommandAction, the CommandName is &#8220;ShowParticles&#8221; and the AssociatedObject is ParticlesBehavior.</p>
<p><a href="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec6.png"><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec6.png" alt="" width="503" height="279" /></a></p>
<p>Back to the issue of the never-ending particles. To fix this, we need just one set of changes to ParticleControl. The UpdateParticles method is the heart of the control and is called each time the Silverlight rendering process renders a frame. It updates existing particles, creates new particles, and removes expired particles. The particles are created 10 at a time until the particles collection reaches the MaxParticleCount. But because particles are also being removed from this collection the result is a never-ending flow of particles. Change <strong>this.particles.Count</strong> to <strong>totalParticlesCreated</strong> and define it as a private field at the top of the class definition as type int. At the end of the SpawnParticle method, increment the totalParticlesCreated value by one. Now the control will create particles until MaxParticleCount is reach and stop.</p>
<p>We have a fully-functioning ParticlesBehavior.</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec7.png" alt="" /></p>
<p>The last thing I did was add the dependency properties from ParticleControl (StartColor, EndColor, Fuzziness, MaxParticleCount, OriginVariance, Speed, ParticleSize, ParticleSizeVariance, Life, and LifeVariance) to ParticlesBehavior and set the values for each created instance of the ParticleControl. This gives a nice design-time experience to configure the particles. I changed a few values to better time the particles with the length of the sound played when an item is clicked:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec8.png" alt="" /></p>
<p>There is one final thing we need to do when an item is clicked. Right now you can click on an item multiple times and it will play a sound and generate particles each time. To solve this, we can use the RemoveElementAction. This action removes the targeted element from its parent control. Drag the RemoveElementAction onto the staplerPath object. Since the trigger defaults to EventTrigger and MouseLeftButtonDown and the TargetName defaults to the AssociatedObject then we don&#8217;t have to change anything:</p>
<p><img src="http://www.shazaml.com/wp-content/uploads/2009/09/091809_0325_HiddenObjec9.png" alt="" /></p>
<p>When we click on the staplerPath then it will:</p>
<ul>
<li>Change the opacity of its corresponding TextBlock (ChangePropertyAction)</li>
<li>Play a sound (PlaySoundAction)</li>
<li>Spray particles (ParticlesBehavior)</li>
<li>Be removed from its parent control (RemoveElementAction)</li>
</ul>
<p>Download the <a href="http://www.shazaml.com/downloads/ClutteredCubeSource4.zip">source</a> for this episode.</p>
<p>In our <a href="http://www.shazaml.com/archives/hidden-object-episode-5">next episode</a>, we will use a magnifer pixel shader effect wrapped in a behavior to allow the user to zoom in on portions of the image.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.shazaml.com/archives/hidden-object-episode-4/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
