Posts tagged ‘Silverlight’

How To Animate a Changing Property in a Custom Control in Silverlight

For my recent visualization, I created a custom control in Silverlight that animated the color of a Path every time a “Fill” property on the control was changed. I thought I would pass along my learning from this process.

First thing I learned was that you cannot use TemplateBinding in a Storyboard (I think). I asked this question on Stack Overflow and I haven’t gotten an answer. But I’m pretty sure that in Silverlight you cannot use TemplateBinding to attach a property to a KeyFrame value. This means that you have to have a pointer in the control code the allows access to the KeyFrame so you can update the value.

I’ll walk through the conceptual part of animating a property in a Custom Control in Sivlerlight and then walk through the code to it.

Step 1: Create a PART to your control to hold the Storyboard and a PART to hold the KeyFrame you want to manipulate

I cover how to make a PART to your control here because it was too much to put into a single blog post. You’re going to want to make your Storyboard a PART that is accessed via resources (via MyControlName.Resources[MyStoryboardName]) and your KeyFrame should be a PART that is accessed the normal way (via the GetTemplateChild(MyKeyFrameName) method).

Step 2: Create the DependencyProperty you want to drive the animation

Yet another chance for me to endlessly flog Robby Ingebretsen’s awesome Silverlight Code Snippets. If you use these, use ‘sldpc’, which is the DependencyProperty with a property changed callback. We want to manually fire the animation when the property changes, so we’re going to do that in the callback.

If you don’t want to use Robby’s stuff, here’s the code for a DependencyProperty with a property changed callback. Because my visualization animates the color, I called my property “Fill”.

public SolidColorBrush Fill
{
    get { return (SolidColorBrush)GetValue(FillProperty); }
    set { SetValue(FillProperty, value); }
}

public static readonly DependencyProperty FillProperty =
    DependencyProperty.Register("Fill", typeof(SolidColorBrush), typeof(County),
    new PropertyMetadata(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), new PropertyChangedCallback(OnFillChanged)));

Step 3: Hook up a property changed callback and run the animation

Then, all you need to do is go into the property changed callback that you have created and assign your the new valie of the property to the keyframe value of the animation you want to run. Then run the animation.

private static void OnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    MyControlType thisControl = d as MyControlType;
    if ((thisControl != null) && (thisControl._myStoryboard != null))
    {
        SolidColorBrush newBrushHolder = (SolidColorBrush)e.NewValue;

        thisCounty._myKeyFrame.Value = newBrushHolder.Color;
        thisCounty._myStoryboard.Begin();
    }
}

And now every time you change that value in the control, it will animate to the new value. Simple as that.

How To Create a PART in Your Silverlight Custom Control

There are about a dozen videos and tutorials on how to create a custom control in Silverlight 3. (Here’s my favorite, from Karen Corby. Skip to about 47 minutes for the tutorial part.)

But sometimes, you (and by “you”, I mean me) need help figuring out how to create a PART for a control because, let’s be honest, you don’t do it all the time and no one has a blog post on just this little part of control building.

If you’re wondering what a PART is, here’s a short explanation: A PART is a naming convention that allows a control (code) to make a contract with the control template (XAML) in Silverlight. The control says to the template, “I’m going to be doing something programmatic with this part, so it better be there”. The template responds, “Here’s that part you wanted.”

I not actually talking down to anyone, this is really how my brain works.

There are basically five steps in creating a PART. I think you can actually do it in less, but I’m trying to follow what I think is proper coding practice. In this tutorial, we’re going create parts out of a Button and also a Storyboard (partly because there are different ways to assign a PART if it is in located in the control resources like a Storyboard is).

Step 1: Define the control template parts you’ll need

Outside of the control class we need to add the TemplatePart attributes. Inside the class, we need to define the names of the UI objects we’re going to turn into parts as well as create some corresponding objects in the control so we can access those PARTs.

[TemplatePart(Name = MyControl.StoryboardString, Type = typeof(Storyboard))]
[TemplatePart(Name = MyControl.RootElementString, Type = typeof(FrameworkElement))]
[TemplatePart(Name = MyControl.ButtonString, Type = typeof(Button))]

public class MyControl : Control
{
    private const string StoryboardString = "PART_MyStoryboard";
    private const string RootElementString = "PART_RootElement"
    private const string ButtonString = "PART_MyButton";

    private Storyboard _targetStoryboard;
    private FrameworkElement _rootElement;
    private Button _targetButton;

What we’re going to do here is remarkably stupid because I don’t have the creativity right now to do something cool. When we press the button, we’ll play the storyboard. We need the RootElement because… you’ll see in a moment.

Step 2: Make sure you have a XAML template properly named to correspond with the part

We have three parts we’re getting here, so this is a stripped down template that just has the three PARTs named appropriately. If the names are not the same as the strings above, it will not work.

<StyleTargetType="local:MyControl">
    <
SetterProperty="Template">
        <
Setter.Value>
            <
ControlTemplate TargetType="local:MyControl">
                <
Grid x:Name="PART_RootElement">
                    <
Grid.Resources>
                        <
Storyboard x:Name="PART_MyStoryboard">
                          
<!– Whatever animations you want here –>
                      
</Storyboard>
                    </
Grid.Resources>
                    <
Button x:Name="PART_MyButton" />                       
                </
Grid>
            </
ControlTemplate>
        </
Setter.Value>
    </
Setter>
</
Style>

Step 3: Assign the XAML PART to the code PART in the OnApplyTemplate method

Now we just have to write a custom OnApplyTemplate method that will grab the XAML elements and assign them to objejcts within the control code. There are two key methods you’ll use. The first is GetTemplateChild, which will pull out any UI element in the XAML that is named and not in the resources.

If you want to get something in the resources, you need to refer to the UI element that holds those resources. This is why we needed the root element as a PART. So, enough of my blabbing… here’s the code:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    _rootElement = GetTemplateChild(MyControl.RootElementString) as FrameworkElement;
    //Make sure we actually got the template applied.
   
if (_rootElement != null)
    {
        _targetStoryboard = _rootElement.Resources[MyControl.StoryboardString] as Storyboard;
        _targetButton = GetTemplateChild(MyControl.ButtonString) as Button;

        _targetButton.Click +=new RoutedEventHandler(_targetButton_Click);       

    }
}

Now we have all the PARTs assigned so we can do something like adding an event handler to the Button so that, when it is clicked, it runs the storyboard.

void  _targetButton_Click(objectsender, RoutedEventArgs e)
{
     _targetStoryboard.Begin();
}

And that’s how you add a PART… both in the regular XAML template and in the resources of the template.

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.

Trigonometry and Interaction Design

Over at Project Rosetta they have the post I’ve been waiting for: How to use mathematics to enhance user experiences.

They basically walk step by step through how we can use mathematics to create easing equations and pseudo-3D effects. They then use these principles to create the following application. Click and drag on a name to spin the interface.

Get Microsoft Silverlight

Awesome.

Head First C#: Silverlight Supplement For Chapter 1 (pages 8-16)

Silverlight Concepts Covered:

  • Building a basic Silverlight project
  • Creating code behind for a event triggered by the user
  • Creating an HTML alert (a fake MessageBox) in Silverlight

Project Files are available for download at the bottom of the page.

Because I’m an interaction designer and not a coder, I find that there are certain things that can be very limiting for me. I’ve decided to fix that by learning how to code properly. To do so, I’m using a book that actually makes sense to me: Head First C#. If you’ve never used the Head First series, its generally a pretty good series zero-to-sixty book on the given topic which teaches by doing (the only way I’ve found I can learn anything).

Sadly, Head First C# currently uses WinForms for all user interfaces. This is the beginning of a series in which I’ll go through the book, but replace all the WinForms with Silverlight. I will very purposely not give the rest of the lessons because I have a nagging moral qualm in the back of my mind about taking someone else’s intellectual property and putting it up on my blog. Call me old fashioned.

I will, however, be going through the project and offering alternative code downloads of the projects (with Silverlight interfaces). I figure that, because the Heads First books allow free downloads of their project code on their website, they don’t mind me doing this on mine. If anyone from O’Reilly is reading this and disagrees, just let me know.

The first chapter has you building a program for entering and saving Contacts from start to finish. I will be pointing to the pages and listing alternative Silverlight steps

Pages 8-16

1. Start Visual Studio 2008 and select “Silverlight Application” from your list of options. The default “Web Page” options should be fine for what we’re doing.

clip_image001

2. Open up Expression Blend 2.5 (I’m using the June 2008 Preview) and find your project and open it.

clip_image001[12]

3. Double Click on the Page.xaml file to open it up in Blend. We’re going to create the basics of our user interface here.

4. Go ahead and grab the “Objectville Paper Co” image from the Heads First web site. Right click on your project in Blend and select “Add New Folder”. Name your new folder “Images”. Right click on that folder, click “Add Existing Item…” and navigate the graphic you downloaded. Your project should look something like this:

clip_image001[14]

5. Drag the image from the project to the canvas. Things may look a little crowded on the canvas, so lets make it a little bigger. Click the “Properties” tab (a) on the right side of Blend and make sure you have UserControl (the highest object in the tree) selected in the “Objects and Timeline” (on the left side) (b). Change the Width to 600 and the Height to 800 (c).

(a)

clip_image001[16]

(b)

clip_image001[18]

(c)

clip_image001[20]

6. You’ll probably notice that our images got stretched. We’re going to follow the spirit of HFC# and change it to be an unstretched size. Select the Image from your Objects and Timeline and set Stretch to None, HorizontalAlignment to Left and VerticalAlignment to Right.

clip_image001[22]

clip_image001[24]

7. Before we run the project, let’s change the background so we can tell where our page is. Select the LayoutRoot and change the Background to something not white (I chose a light blue). Save All in Blend and click on your open Visual Studio 2008 and hit F5. (I haven’t had a lot of luck getting Silverlight projects to run from Blend)

OK, that gets us to page 14. The next step is to add extra code to the auto-generated code in Visual Studio.

8. Go back to Blend and click on the Image and go to the Events section (the little lighting icon) of the Properties tab. This will give you a list of all the events available for the Image control.

clip_image001[26]

9. In MouseLeftButtonUp, type the name of the method you want called when the Image registers a MouseLeftButtonUp event (I typed ImageClick) and hit enter.

clip_image001[28]

10. Blend will communicate to Visual Studio, which will in turn auto-generate all the code you need for that event handler. It should look something like this:

private void ImageClick(object sender, MouseButtonEventArgs e)

{

}

11. Type the following at the top of the page:

using System.Windows.Browser;

and then type the following into the ImageClick method:

HtmlPage.Window.Alert(“Contact List 1.0. \nWritten by: Your Name”);

Run your project.

From here, HFC# walks through creating a database. The next installment will pick up after the database is created and we get to bind the data to our interface.

Download Project Files for this post: HFCSharp Part 1 Project Files