Create A Snapping Slider In Blend Using Behaviors (Silverlight 3 or WPF)

UPDATE: It turns out that in WPF, there is an easier way to snap the slider. For integers, simply check the “IsSnapToTickEnabled” and set your TickFrequency accordingly. Which means that this behavior is really only useful for Silverlight, which doesn’t have those properties.

Behaviors are easily the coolest thing that has ever happened to anything.

Perhaps I overstate my case somewhat. But they’re still pretty cool.

To me, a wonderful example is the ability to let designers/developers get some really cool functionality out of the Silverlight or WPF slider.

Now, one might normally think that there is a simple way to make your slider values to snap to an integer or to some incremental number (perhaps base 2 or base 10). Alas, one would be wrong. There have been a couple solutions to this problem (see here and here), but they usually involve creating a new slider subclass with the additional functionality if you really want the interaction to be reusable.

However, behaviors makes all this unnecessary. What is even better is that there is no code difference between WPF and Silverlight on this one. That’s right… this tutorial and the code that goes with it works exactly the same in Silverlight as it does in WPF.

SnappingSlider Behavior (SnappingSlider.cs) – Works for Silverlight and WPF

WPF SnappingSlider Behavior (All Project Files)

Silverlight SnappingSlider Behavior (All Project Files)

You can also download the behavior here (just the cs file) which would make me happy because it ups my street cred among the Silverlight homies (says the whitest man on earth).

If you want to learn how to create it yourself, let’s get started.

In your project in Blend, right-click on the project and go to “Add New Item…”

clip_image001[4]

Choose “Behavior” from the list and type in the name of the behavior you want to create

clip_image001[6]

This is where Blend is way cooler than Visual Studio… it gives you pretty much all the code and imports all the appropriate references for creating a behavior. So, first change the behavior associated object type to a Slider:

public class SnappingSlider : Behavior<Slider>

And go into the inside the OnAttached method, enter the following code:

AssociatedObject.ValueChanged +=new System.Windows.RoutedPropertyChangedEventHandler<double>(AssociatedObject_ValueChanged);

Hint to Code Newbies: If you get to the “+=” part and hit the Tab key twice it will add the necessary code.

Inside the AssociatedObject_ValueChanged method, I added the following code:

private voidAssociatedObject_ValueChanged(objectsender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
{
  
//Let the slider be equal to the Maximum and Minimum values
  
if((e.NewValue != AssociatedObject.Maximum) && (e.NewValue != AssociatedObject.Minimum))
    {
      
//Using the Minimum value as a starting point, only allow values that are
        //   a multiple of the SmallChange value. If you want to simply round to
        //   integers, set it so that:
        //   SmallChange = 1
      
doublecalcValue = Math.Floor((e.NewValue – AssociatedObject.Minimum) / AssociatedObject.SmallChange);
        calcValue = (calcValue * AssociatedObject.SmallChange) + AssociatedObject.Minimum;
        AssociatedObject.Value = Math.Round(calcValue);
    }
   
else
   
{
       
//Sometimes it hiccups on me, so I used this to catch those
       
AssociatedObject.Value = Math.Round(e.NewValue);
    }
}

Once you have that code in place, build the project (menu option Project –> Build Project).

Now you should have the behavior available in the “Assets” tab under “Behaviors” (at the bottom of the picture below).

clip_image001[8]

 

Just drag it onto your Slider and set the Minimum, Maximum and SmallChange properties appropriately. Remember that SmallChange is the value is that is acting as your increment controller.

Adobe Illustrator To XAML Conversion Options

One of the things that I’ve been doing as I was working on my Florida Crime Rate data visualization was finding vector maps of the US and converting them into XAML. Pretty much everything I found that was free was in SVG format, so I would pull that into Adobe Illustrator and then export into XAML using Mike Swanson’s really awesome Adobe Illustrator to XAML export plug-in. But I wanted to take a moment and say why I’m still using this plug-in instead of the default Expression Blend Import for Illustrator.

As a case study, let’s look at an SVG file of the US counties. (You can find a link to the SVG here. Here is the file converted to XAML if you just want to download that and not mess with any of this other stuff. Special thanks to Nathan Yau of Flowing Data and @SimonRegenbogen for helping me find this.)

clip_image001[5]

The SVG is about 1.6 MB, but when I convert it to XAML, it sees a size reduction of about 20-25%.

clip_image001

You’ll notice that the Adobe Illustrator-to-XAML export is about 100 KB smaller than the Expression Blend Illustrator Import. What’s the difference?

  1. AI-to-XAML preserves path layers and grouping – In the native import version, all the paths are imported into a single Canvas. This makes it really hard to isolate paths and work with them individually. The AI export version groups into separate Canvases so that each state is it’s own canvas. Very handy.
  2. AI-to-XAML preserves some metadata – all the paths in the AI-to-XAML version have a comment preceding the path that contains some (not all) of the naming metadata from the SVG file.
  3. AI-to-XAML spaces code out better – Here is a sample of the data from the AI-to-XAML version:
  4. clip_image001[9]
    And here is the same path in the native import.

    clip_image001[7]

    You’ll notice three things: the first is the metadata (already noted). The second is that the export plug-in has spaced the paths to make them easier to read. The third is something you’ll notice if you’ve spent a lot of time working with XAML paths… the point data is spaced out in a way that makes it much more readable.  Overall a much better XAML experience.

  5. AI-to-XAML maintains less path data fidelity – The AI-to-XAML converts to 3 decimal places, while the native import converts to 4 decimal places. But this isn’t necessarily a bad thing. Here is a corner of Sacramento County zoomed in 6400%.
  6. clip_image001[11]

    Now let’s change the path data by a hundredth of a unit, from X=35.366 to X=35.376

    clip_image001[15]

    The difference is almost imperceptible… even at this level of magnification. Changing it by a thousandth of a unit is going to make almost no difference that users will be able to see.

Conclusion: I’m going to continue using Mike Swanson’s Adobe Illustrator to XAML Export plug-in because it is awesome. If you don’t have or can’t afford Adobe Illustrator, the default import isn’t bad, but it is missing a good deal of potentially valuable functionality.

Florida Crime Rates – An Information Visualization in Silverlight

I’ve always loved interactive information visualization, and have been particularly interested in building visualizations in Silverlight. (You can see a visualization I did for a ticket to the MIX 2009 Conference over here.) I’ve always thought that Silverlight, with its fantastic (and flexible) animation engine and the awesome data tools that .NET gives developers, is a perfect fit for info visualization projects.

Over the next week or so, I’m going to be putting up posts on how I created this interactive visualization of Florida crime rates. But for the time being, you can download the project files and check it out.

Note: As of September 1st, we’re having some weird issues with the initial loading and display. If you move the slider, everything will start working again… Will try to fix.

[silverlight: CountyTest/CountyTest.xap, 450, 466]

Interested in implementing visualizations for your projects? Feel free to contact me at Veracity Solutions via e-mail. My address is matthias – at – veracitysolutions – dot – com

Silverlight Buttons with Rounded Corners (The Super Easy Way)

Download the “Silverlight Buttons With Rounded Corners” project files

This is a really silly but effective way of giving a button rounded corners without having to create a custom control template for that Button.

First, install Pete Blois’ Expression Blend Samples. It’s a set of Behaviors and Triggers for Blend. For reasons I don’t really understand, these don’t automatically show up in my Blend Behaviors list, so if you have the same problem (or if you don’t want to install all the behaviors) follow these steps:

  1. create a new class in your project and name it ClippingBehavior.cs
  2. copy all the code in this text file into your class, replacing the ClippingBehavior class that was auto-generated
  3. drag a behavior onto your canvas and delete it. This is by far the quickest and easiest way of getting the appropriate references added to your project. Sad but true.
  4. Add “using System.Windows.Interactivity;” to your ClippingBehavior.cs references.
  5. Hit F5

OK… with the behaviors added into Blend Assets menu, create a Border with the rounded corners you want your button to have. In order to show that this is pretty flexible, I gave my border a CornerRadius of “20,2,20,2”

Now, put a Grid inside of that border and a button inside of the grid. Give your Button has a negative margin at least equal to the largest CornerRadius margin. It should look something like this:

clip_image001 clip_image001[4]

Now, go to the Behaviors section in Blend and choose ClippingBehavior and drag it onto the Grid.

clip_image001[6]

Give it a Margin equal to your BorderThickness and give it the same CornerRadius as your Border.

clip_image001[8]

One last thing, make sure that your Border has the same BorderBrush as your Button. You can do that by clicking on the box next to the BorderBrush property and going to “DataBinding”.

clip_image001[10]

Select the “Element Property” tab, find the button you’re giving rounded corners and select the “BorderBrush” property from the Button.

clip_image001[12]

And you’re good to go. Now this doesn’t really give the actual Button rounded corners, but it sure does look that way.

clip_image001[14]

And you’ve saved yourself a good deal of heartache (and a whole ton of generated code) because you don’t have to create a whole new Button template just to change some corners on one or two buttons.

Creating a Programmatic Path in Silverlight (or WPF)

Download Project Files for Creating a Programmatic Path in Silverlight or WPF

(Note: The project is in Silverlight, but if you copy and paste the code into a WPF project, it should work without any changes)

Have you ever wanted to create a Path programmatically or create a Path in code behind or dynamically build a Path or hand code a Path in Silverlight or WPF?

Yes, I just said the same thing 4 different ways, but I’m trying to cast a wide net for Google to catch. One of the biggest troubles I have when I’m trying to do something new is that I don’t always know the proper terminology, so I try to think of all the ways people might want to ask the question.

I’ve been playing around with a good number of information visualization concepts recently and one thing that I’ve found that I needed was the ability to create a path programmatically.

One way to do that is to tackle and fully grok the Path data code system. (Good guides to it are here and here.) This system is really cool, but (unless I’ve missed something) they cannot be animated.

I wanted to build a path based off a data set, but that means that I have to build it programmatically. I didn’t find a lot of useful stuff on how to do this, so I thought I’d throw some out there.

First, because I’m a XAML guy, I’m going to provide a simple XAML example of a Path that can be animated:

<Path x:Name="MyPath" Fill="#FFA30000" Stroke="Black" Width="100" Height="100">
    <
Path.Data>
        <
PathGeometry FillRule="EvenOdd">
            <
PathFigure IsClosed="True" StartPoint="0,0">
                <
LineSegment Point="0,100"/>
                <
LineSegment Point="100,100"/>
                <
LineSegment Point="100,0"/>
            </
PathFigure>
        </
PathGeometry>
    </
Path.Data>
</
Path>

This path is a simple square and looks like this:

clip_image001

Now, let’s assume you want to recreate this programmatically using a collection of points that represent X,Y coordinates. If you’re using an ObservableCollection of Points (like I am) you can use the following method to return an the appropriate path.

Path createPath(ObservableCollection<Point> rawData)
{

    Path FinalPath = new Path();
    PathGeometry FinalPathGeometry = new PathGeometry();
    PathFigure PrimaryFigure = new PathFigure();

    //if you want the path to be a shape, you want to close the PathFigure
    //   that makes up the Path. If you want it to simply by a line, set
    //   PrimaryFigure.IsClosed = false;
   
PrimaryFigure.IsClosed = true;
   
    PrimaryFigure.StartPoint = rawData[0];

    PathSegmentCollection LineSegmentCollection = new PathSegmentCollection();

    for (int i = 1; i < rawData.Count; i++)
    {
        LineSegment newSegment = new LineSegment();
        newSegment.Point = rawData[i];
        LineSegmentCollection.Add(newSegment);
    }

    PrimaryFigure.Segments = LineSegmentCollection;
    FinalPathGeometry.Figures.Add(PrimaryFigure);
    FinalPath.Data = FinalPathGeometry;

    return FinalPath;
}

Once you have the path in place, you can just add it to your layout and it should show up. If you’re still confused, you can download the project that I created this in and walk through the rest of it yourself.

How To Create A ListBox with CheckBoxes (or RadioButtons) In Silverlight 3

To set the scene: You have a ListBox that is being populated by some collection and you want the user to scroll through the ListBox and either check a bunch of things or check one thing. Basically, you want a list of checkable items. If this is what you’re trying to do, this is the tutorial that lets you do it without any code… simply by applying a style to your ListBox.

Download finished tutorial: ListBox With CheckBoxes (or RadioButtons) Project in Silverlight 3

Go here to see the final result.

First, you should know right off the bat that this tutorial is for Silverlight 3 only. It uses a data binding functionality called RelativeSource binding that isn’t available in earlier versions of Silverlight.

OK… to start out, right click on your ListBox and go to:

Edit Additional Templates –> Edit Generated Item Container (ItemContainerStyle) –> Edit a Copy…

clip_image001

Name your new template and Blend will generate the default ItemContainerStyle for the ListBox.

Split up the grid so that there is room for your CheckBox or RadioButton. I’m going to put mine on the left, set HorizonalAlignment and VerticalAlignment to “Center”, reset the Content property" and make the whole thing twice as big by setting the RenderTransform X and Y to 2.

clip_image001[5]

If you’re really picky about making sure that your CheckBox is centered appropriately, change the Width and Height to “16”.

OK… so we’ve got the CheckBox in there, but it doesn’t really do anything. So let’s set the binding so that it works. Sadly, Blend doesn’t have an obvious way (that I can see) of setting a RelativeSource binding, so just type this into your CheckBox (or RadioButton):

IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Mode=TwoWay}"

This binding will make it so that when the user selects or unselects an item, the CheckBox or RadioButton will reflect this decision. Similarly, when the user checks or unchecks the CheckBoxes or RadioButtons, the selection will reflect these actions.

Now, we just need to make sure our selection option on the ListBox reflects our interface choice. If you’re using CheckBoxes, make sure that your ListBox SelectionMode is set to “Multiple” or “Extended”.

clip_image001[1]

If you’re using RadioButtons, it needs to be set to “Single”.

And you’re done! You can now set any ListBox to hold a list of checkable items simply by assigning it this ItemContainerStyle.

CheckBoxRadioButtonExample

And you should have something that looks and acts like this.

How To Get a Silverlight 3 AutoCompleteBox To Show Sample Data in Blend 3

Download Project Files for AutoCompleteBox Sample Data Project

So you’re playing around with Silverlight in Blend 3 and you set up some sample data. (If you don’t know how to do that, I’ll get to that in this tutorial too.) Your sample data is all set up and you’ve attached it to your AutoComplete box… but nothing happens. You get angry and throw your computer out a window (unless it’s a MacBook, in which case you apologize to it for flirting with Microsoft technologies and take it for a little cuddle), but you eventually think you want to try again and so you go looking for the problem on the internet. Hopefully that is what brought you here.

I talk too much, I know.

Just to start out at the beginning, if you didn’t know that Silverlight 3 had an AutoCompleteBox, that’s because it isn’t a default control. You can install it and several other fantastic controls via the Silverlight Toolkit. If you don’t have this installed, do so now.

With the Silverlight Toolkit installed, let’s just make sure we have the right problem.

OK… lets create our sample data. In the top right corner of Blend, you’ll see a couple of tabs. Click on the “Data” tab and click on the “Add sample data” menu and choose “Define New Sample Data…”

clip_image001

Name your database something short (you’ll see why later) and rename the “Collection” collection to something less confusing, like “Sample”. Add some string properties and give them handy names. You can see my sample data as a starting point…

clip_image001[5]

That’ll do for now. Now, draw an AutoCompleteBox into your UserControl and drag the Sample collection on top of it. It will set itself to be the default ItemsSource. Now, hit F5 to run your application. It should act like this one below… if you type stuff, nothing comes up… but if you type “e”, you can see (in my sample, at least), it shows a set of items labeled, “Expression.Blend.SampleData.AutoData.SampleItem”.

clip_image001[1]

This is because the filter being used by default in the AutoCompleteBox takes the items and converts them directly to strings. If the item itself is an object (like this example and like most real data you’re probably using), it will convert it into the string representation of that data type.

So let’s fix it. First, we’re going to create an ItemTemplate for our AutoCompleteBox so that we can actually see the data in it. The quickest way to do this is actually kind of silly. Create a ListBox in your app and drag the data collection into it. It will auto-generate a super simple ItemTemplate. Then right-click on your AutoCompleteBox and go to “Edit Additional Templates –> Edit ItemTemplate –> Apply Resource –> [name of generated template here]”

clip_image001[7]

Delete your ListBox, just to clean things up.

Now you’ll have an AutoCompleteBox that shows the data like you want it, but it’s still looking at the “Expression.Blend.SampleData.SampleItem” when you type in the box, so it’s not acting the way we want. In order to do that, we just have to override the “ToString()” method in the AutoData. Open up “AutoData.xaml.cs”

clip_image001[1]

Scroll down to the “SampleItem” class and make the beginning of that class look like this:

public class SampleItem : System.ComponentModel.INotifyPropertyChanged
{
    public override string ToString()
    {
        return Name;
    }

If you want to use another property as your text return, just use that property name instead of Name. If you want to use a combination of properties, you could do something like this:

return Name + " - " + CompanyName;

Although, if you want it to look at two fields, you should change the FilterMode to “Contains”

clip_image001[3]

And… tada! You’re done… unless you want to give it some styling to better enhance the user experience (like putting the name at the top so that it draws the eye).

clip_image001[3]

Also valuable, check out Tim Heuer’s post on turning the AutoCompleteBox into an editable ComboBox.

How To Wrap Text in a Silverlight 3 ComboBox

Download ComboBox TextWrapping Tutorial Project

Sometimes you just want stuff to work the way you want it to work. I want a property on the Silverlight ComboBox that says “WrapText”. But alas there is not one, so I have to do it myself.

So your ComboBox looks like this:

and you want it to look like this:

clip_image001[13]

Let’s make that happen.

First, we need to make sure that the DataTemplate is going to act in such a way that it is compatible to having the data inside it wrap.

So… right-click on your ComboBox and go to: “Edit Additional Templates –> Edit Generated Items (Item Template) –> Edit Current”

clip_image001[5]

If that option isn’t available, go to “Create Empty” The DataTemplate in my sample looks like this:

clip_image001[7]

Hopefully, you have the binding information available for your data. If not, check out this post on creating sample data for the purpose of styling things. Make sure all the Widths and Heights (but especially the Widths) are set to “Auto”.

clip_image001[9]

And make sure your TextBox or TextBlock has TextWrapping=”Wrap”

clip_image001[11]

So now your ComboBox wraps in the main section… which is awesome, but you still have this happen when you open up the DropDown (PopUp)

clip_image001[15]

If you want that to wrap as well, the solution isn’t hard so we’ll deal with it here instead of giving it another post.

First,change the HorizontalContentAlignment on the ComboBox to be “Stretch”.

clip_image001[17]

Next, right click on the ComboBox and go to “Edit Additional Templates –> Edit Generated Item Container (ItemContainerStyle) –> Edit a Copy…”

clip_image001[19]

What is happening is that the ItemContainerStyle element is requesting all the space in the world from it’s parent and since the parent with the ultimate authority is a PopUp, it sees no reason to constrict the ItemContainerStyle with irritating constraints, so the text element finds no reason to start wrapping. So, we’re going to tell the ItemContainerStyle that it can only request a certain amount of space. In this particular case, we’re going to set MaxWidth=”200”

clip_image001[21]

And we get this:

finalcomboboxwrapping

And we’re happy.

Or at least I hope we’re happy. If you’re not happy, mention your problem in the comments and I’ll try to get back to you with any tweaks or updates you need.

Styling A ComboBox In Silverlight 3

Download ComboBox Styling Project Files

This post is meant to be a center point for topics related to styling the Silverlight 3 ComboBox. It will go over the basic about ComboBox styling and will also get updated with links to tutorials about common design problems with the ComboBox.

So, let’s get started…

If you want to change the look of the main ComboBox or the ComboBox drop down (popup),

clip_image001[6]

clip_image001[4]

you’re going to want to change the main template of the ComboBox.

As an aside, in order to make this as simple as possible, we’re not going to connect out ComboBox to any data… we’re just going to add a bunch of ComboBoxItems to it. To do this, click on the double-arrow at the bottom of the toolbar and type “combo” into the search field.

clip_image001[10]

Click on the ComboBoxItem and draw it into the ComboBox a couple times. This will give your items some weird heights and widths, so change those if that bothers you. We now have enough items to be able to see the drop down for the purposes of styling it.

OK… let’s get started with actually working on the ComboBox template. Right click on the ComboBox and going to “Edit Template –> Edit a Copy…”

clip_image001[8]

This will dump a copy of the default ComboBox style and template into your resources that you can play around with.

Let’s say we want to do something as simple as changing the corners in the main comboBox and the drop down to make them a little more rounded.

When we look at the template, we should see something that looks like this:

clip_image001[12]

Let’s start with rounding the corners of the pop-up, since we can do that from right here. On the PopupBorder element, let’s change the CornerRadius to “0,0,16,16”. And let’s change the border color and thickness just cause we wanna. We end up with something like this:

clip_image001[16]

Now, lets work on changing the corners on the rest of the ComboBox. As it turns out, most of the visual elements in the ComboBox are in the DropDownToggle ToggleButton and go to ControlTemplate by right clicking on it and going to “Edit Template –> Edit Current”

clip_image001[18]

Now, we can see 8 rectangles that make up the design of the ComboBox. If you wanted to simplify the design, you could get rid of them and put something else in, but we’re going to assume for the moment that you just want to change the corners. Go through the rectangles and if RadiusX and RadiusY are 3, change them to 16 an if they are 2, change them to 15.

clip_image001[20]  becomes clip_image001[22]

And you have something that is… not that attractive, but it is definitely different.

MIX09 Ticket Winners from Veracity

What’s better than going to MIX09?  Going to MIX09 for free!

Congrats to Matthias Shapiro and Jason Alderman, two Veracity rockstars who won Tim Heuer’s having fun with Silverlight contest and scored free admissions to next month’s conference.

Going to MIX?  See you there!