Monthly Archives: June 2009

TechFriday: Building Custom Behaviors

Okay, I missed Tech Friday, so I decided to make it Tech Weekend instead. I attended the June Mix-It-Up: Re-MIX last Thursday and was able to catch up a bit on the new technologies. I have been busy with a few other things at work and I am ashamed to say, I have been lagging behind! 😐

One of the things that interested me is behaviors in Silverlight 3. If you do a bit of searching you’ll find quite a few articles on behaviors. Basically, it’s the ability to encapsulate “behaviors” that you can reuse on different UIElements that developers can write and have their designers use (with drag and drop of course) to earn brownie points. Expression Blend 3 comes with a few behaviors out of the box. They’re the ones listed in the screen shot below, apart from the first one which is the behavior I created:

image

My favorite, I would have to say is the MouseDragElementBehavior. To use it, all you have to do is drag and drop it to any element in your app to enable drag and drop capabilities. There’s just so much you can do for interactivity with that behavior alone. I remember this being one of the things I use to code time and time again with previous projects I used to tinker with.

Another behavior that I’ve always wished I could encapsulate was the “bring to front” behavior. Say you have a bunch of UI elements scattered in a pile on the screen, you sometimes want it to behave in such a way that an element you click on gets floated to the top. This is probably a behavior that you would like to use in several scenarios/apps so it makes sense to build a behavior for it, and reuse it across different projects.

WARNING: I think I’m using a different build of Blend so I won’t get into the details of where to get which assemblies. I’ll update this post once Blend 3 is out, but I think what’s more important is understanding how building a behavior would be like more or less.

Basically what I did was build a Silverlight Class Library that inherited from the Behavior generic:

public class BringToTopBehavior : Behavior<Canvas>
{

//some code here

}

When creating your own behaviors, Canvas would be the object you would like to apply your behavior to. Next thing to do is override the onAttached() method:

protected override void OnAttached()
{
    base.OnAttached();

    AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
    
}

AssociatedObject would be the the actual instance to which the behavior is attached. What I did here is add an event handler to the Loaded event because I wanted to attach another event handler to each of the objects that gets loaded into the canvas. I can only get the children once the UI element has finished loading. My Loaded handler looks something like this:

 

void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
 {
   
     foreach (var child in AssociatedObject.Children)
     {
         child.MouseLeftButtonUp += child_MouseLeftButtonUp;
     }
 }

What I’m doing is attaching a handler to the MouseLeftButtonUp event for each of the objects contained in the Canvas in question. This handler is defined as:

void child_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    BringToTop(sender);
}

I created a few private methods to handle sorting the z-orders of the elements contained in the Canvas:

private void BringToTop(object element)
 {
     
     Canvas p = (Canvas)((FrameworkElement)element).Parent;
     int z = getHighestValue(p);
     for (int i = 0; i < p.Children.Count; i++)
     {
         var child = p.Children[i];
         if (element.Equals(child))
         {
             child.SetValue(Canvas.ZIndexProperty, z);
         }        
     }
 }

 private int getHighestValue(Canvas p)
 {
     int highest = 0;
     foreach (var child in p.Children)
     {
         var val = (int)child.GetValue(Canvas.ZIndexProperty);
         if ( val > highest) {
             highest = val;
         }
         child.SetValue(Canvas.ZIndexProperty, val - 1);
     }
     return highest;
 }

This probably isn’t the best implementation of this behavior but it gets the job done 🙂

USING THE BEHAVIOR

Once you’ve finished writing your behavior you can compile the code and reference that dll into any of your existing projects and start using the behaviors. Right-click on references, click Add Reference, and navigate to the compiled dll of your custom behavior.

image

Once you’re done, you should be able to make use of this behavior through blend. In my case, I can click and drag BringToTopBehavior to my chosen Canvas and I would see the following:

image

image

Now you’ll notice, however, when I try to drag and drop the behavior to the Grid panel, it tells me that it’s not a valid drop target.

image

This is because, in my definition of my behavior, I’d specified that this behavior can be applied only to Canvases. But now, I realize the same behavior can apply to any Panel object. What I can do now is update my behavior definition to, instead of Canvas, have it apply to Panel instead:

public class BringToTopBehavior : Behavior<Panel>
  {
      //somecode
      private void BringToTop(object element)
      {

          Panel p = (Panel)((FrameworkElement)element).Parent;
          //some code
      }
      private int getHighestValue(Panel p)
      {
          //some code       
      }
  }

With this change, I should be able to apply the behavior to any UIElement inheriting from Panel. I’ve zipped up and uploaded the code for this project. Feel free to download and explore here: Update: I realized that the file I uploaded wasn’t working. I updated the file, you can download it from the expression gallery on http://gallery.expression.microsoft.com/en-us/BringToFrontBehavior

Want to contribute to the gallery? Visit http://gallery.expression.microsoft.com/en-us/site/create

To see a sample application, check out http://www.badgorilla.net/behaviors

For more about the greatness of behaviors, check out this Mix Video: http://videos.visitmix.com/MIX09/C27M and of course the link to the behavior pack used in the demo: http://gallery.expression.microsoft.com/en-us/MIXBehaviorPack

Housekeeping..

I decided to clean up my blog over the weekend. Actually, I was considering for a while there buying yet another domain and starting all over but then I realized, there really wasn’t any point to that. I had just become lazy to maintain this one because I felt it had become a bit messy. So I decided to do a few things: 1. Upgrade my wordpress installation to 2.8 (had been on 2.5 for the longest time :|) and 2. Delete the twitter integration.

1. Surprisingly, it wasn’t as painful as I thought it would be. This guide details everything, i think the most difficult part was step 0, which I skipped. I thought, well, if this installation messes up then I guess it’s time for a restart :p. Luckily, it didn’t. It was just a matter of copying over the new wordpress files and running the script. Definitely not as painful as I had imagined. The upgrade made me feel good, at least gave me a feeling of some sort of freshness. 😉

2. I realized that my twitter integration thingamajig was making me more lazy to blog. Plus, It made my site look like crap whenever there was silence. I realized, if my friends want to read about my twitter activities, they’d probably go to my twitter page. I delete my aggregated twitter posts. Well I guess not all of it, it was too taxing to delete them all so I just went as far back as I could and gave up. I think there are still more in the archives but at least my front page is cleaner now. 🙂

I have decided I should put more effort into blogging, maybe set aside some time in a week at least. I know it’s going to be good therapy for me if I do.

Tech Friday: Your Own Custom Search Providers

Not the most techie thing to do but hey, today isn’t the greatest day to be using much of my brain as most of it is concentrating on agonizing on pain. I was browsing around the blogs I monitor and found a post by Long Zheng talking about a little experiment that showed how much branding had an impact on peoples perceptions about search engines. Check out his post if you want to know more. Down the comments, I found someone saying that he wanted to make it his default browser search and saw that he created a search provider. I tried installing it but I am guessing it only works for Firefox. So I went ahead and created my own which I found was quite easy for IE8, especially with the tools that they have out there.

1. Go to http://www.microsoft.com/windows/ie/searchguide/en-en/default.mspx where they already have a list of popular search providers. They also have a custom-search-provider-generatorer if you want to create one of your own 🙂

image

2. Go to the search page that you would like to create a provider for and search for TEST (all caps). When the results page come, paste the URL in the text box provided and name your custom search provider

image

3. Now you can choose to install the provider straight from the page, but if you’d like to share it on your blog/web page, what you do next is click on View XML. It should take you to a page similar to the one below:

image

4. Next step is to go to File->Save As and save the page to your local drive as anything-you-want.xml and upload it to your webserver, skydrive, or anywhere visible to the internet at large.

5. Now on the page where you want to share your provider, you’ll need a link that will point to the following code "javascript:window.external.AddSearchProvider(‘http://www.aimeegurl.com/blindsearch.xml’);". In my case, i have this page:

image

with the following code to the Add Blind Search link:

image 

And it’s that simple 🙂

I know, I owe a super tech friday next week… especially since I skipped last week! ^_^