Tuesday, December 30, 2008

[Silverlight 2] Unit Testing

This is more for my own reference, but here are some really good links I found to information about using the Silverlight Testing framework available to us.

Unit testing Basics [Jeff Wilcox]
Excellent Step by Step [Jeff Wilcox]
MSDN Download and Info
Basic Asynchronous Step by Step

I am probably abusing the framework with the way I have setup my test scripts, but I was looking to store state between each test so that I would not have to setup my application state every time I moved onto a new test.

I followed the main steps listed by Jeff Wilcox, however, I made a few alterations that would probably make him cringe ;)
  1. In each test cs file, I store an instance of the class I'm testing so that the state can be saved.
  2. In the PreparePage() function for each TestClass I check if that instance has been initialized. If it has, I do nothing, else I set it up. Since PreparePage is called before each TestMethod I want to make sure that my instance remains with the state of it's previous test.
  3. I name my tests, in order, alphabetically... often prefixed with "aa_[DoThis]", "ab_[ThenThis]". Since the tests appear to be ran in alphabetical order I want to keep a very scrict execution order so that my state should be known after every test.
  4. I have made all my Test Classes partial, and have created a seperate file "TestSetup.cs" that acts as a central location for me to decide which scipts I want to run and when. Making the class partial allows me to stick the [TestClass] assmbly directive in another file, which means I can comment out scripts as I see fit.
Example:
GraphicCanvas_test.cs


public partial class GraphicCanvas_test : SilverlightTest
{
private GraphicCanvas myCanvas;

[TestInitialize]
public void PreparePage()
{
if (myCanvas != null) { return; }
myCanvas = new GraphicCanvas();
}

...
}

TestSetup.cs

[TestClass] public partial class GraphicCanvas_test {} // Test script run
//[TestClass] public partial class PaletteManager_test {} // <-- Not run


I'm still playing around with unit testing framework, and I'm probably bending it how it wasn't meant to be bent - but I have yet to see something that would work better for me :)




.

Thursday, December 18, 2008

[Silverlight] Silverlight Spy - Awsome Visual Tool

While googling some random problem I was having, I bumped into this amazing [and free!] tool built by firstfloorsoftware which allows you to inspect any Silverlight application embedded in a given page.
The Explorer presents XAP Package, Isolated Storage, Application Styles, the UI Automation tree and the UI element structure of a Silverlight application. Explore the structure and view and edit the details of the selected UI element in the Details pane. Silverlight Spy works with any web page hosting Silverlight 2 content, just point the browser to the page and let the Spy figure it out.
Already this has saved me tons of heartache, as it allows me to easily traverse the visual tree of my application - which is really handy when I do so many dynamic interactions [adding/removing elements etc...]. And I haven't even begun to use the isolated storage inspection! Check it out :)

http://firstfloorsoftware.com/silverlightspy/introduction/



.

Thursday, December 11, 2008

[C#] Creating Custom Dependency Properties

Oh! I'm so excited... I think I actually got this to work for me :)
Please note that this is for creating simple DependencyProperties... I am not creating an attached property here.

I have a custom user control called GraphicGrid which consists of multiple line elements that draw up a grid. I also have a custom user control called PropertyEditor which allows for easy changes to specific DependencyProperties of a given object. I wanted to be able to change the grid color and grid spacing via the editor, so I decided this was the perfect chance to try and implement custom dependency properties.

Here are the basic steps to setting one up:

Step 1:
Register the custom dependency property. Here I create a new dependency propery and give it a name, what the property type is, what the owning object type is, and then in my case, I register a callback to be ran when the value is changed. Note that you do not need to setup a callback function [use null instead], unless you need specific things to happen when the value is changed:
public static readonly DependencyProperty GridLineStrokeProperty =
DependencyProperty.Register("GridLineStroke",
typeof(Brush),
typeof(GraphicGrid),
new PropertyMetadata(GridLineStrokeChanged));

Step 2 [if you setup a callback]:
If you have setup a callback if the value has been changed, then you need to create that function.
private static void GridLineStrokeChanged(DependencyObject o,
DependencyPropertyChangedEventArgs e)

{
GraphicGrid grid = o as GraphicGrid;

// Color lines.
foreach (UIElement line in grid.LayoutRoot.Children)
{
line.SetValue(Shape.StrokeProperty, e.NewValue);
}
}

Here, I cast the sender to a GraphicGrid, which I believe is acceptable since I have registered the property to GraphicGrid. Then I perform some actions with the new value... in my case I update all the lines in the grid with the new color.

Step 3:
Then, if you wish, you can create a local variable which gets and sets this dependency property.
public Brush GridLineStroke
{
get { return (Brush)GetValue(GridLineStrokeProperty); }
set { SetValue(GridLineStrokeProperty, value); }
}
Step 4:
Update the property at your will and whenever the value is changed, the line color will also be changed!


Update directly via the DependencyProperty:
GraphicGrid newGrid = new GraphicGrid ();
newGrid.SetValue(GraphicGrid.GridLineStrokeProperty,
new SolidColorBrush(Colors.Red));



Update via the local variable:
newGrid.GridLineStroke = new SolidColorBrush(Colors.Red);



BAM! Auto updating lines!!!
Special thanks to bryant on the Silverlight forums :)
.

Wednesday, December 10, 2008

[C#] Loading embedded XAML files into a project

I was looking for a way to load in a XAML file into my project; I wanted to be able to create a nice looking element without having to build it up dynamically in the C# code, and without having to download the XAML file from a server as I have been doing in some other places.

Turns out you can embed a file as a resource in a Visual Studio project and then open the resource and stream it out!
Step 1: Right click on your project folder and add the new or existing resource to your project.

Step 2: Right click the newly added file in your solution explorer, and select "Properties"

Step 3: Change the "Build Action" to "Embedded Resource". Now the file will be built in to your project as a resource and accessible as such.

Step 4: Open up a stream to the resource, read it out into a string and then use XAMLReader.Load to load up the element. I found this code on a forum, so there may be an easier way to do it... but this worked for me.

Stream s = this.GetType().Assembly.GetManifestResourceStream ("myNamespace.myFile.xaml");
string propertyStr = new StreamReader(s).ReadToEnd();
Panel myGrid = (Panel)XamlReader.Load(propertyStr);

And BAM... loaded xaml! Note that your XAML file must contain the namespace information in order for [System.Windows.Markup.]XAMLReader.Load to load correctly.

Example myFile.xaml:
<. Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<. /Grid .>


Have fun :)
.

Monday, December 8, 2008

[Silverlight 2, C#] Make a dashed border "move" [animate]

I was looking to make my newly dashed border on my rectangle look like it was "moving" [as you see commonly in some applications when selecting an item].

To do this I created a doubleanimation on the "StrokeDashOffset" property of the Rectangle.

<. UserControl.Resources .>
<. Storyboard x:Name="LassoAnimation" .>
<. DoubleAnimation
Storyboard.TargetName="lasso"
Storyboard.TargetProperty="StrokeDashOffset"
By="1"
To="8"
RepeatBehavior="Forever"
Duration="0:0:3"
SpeedRatio="3" .>
<. /DoubleAnimation .>
<. /Storyboard .>
<. /UserControl.Resources .>

...

<. Rectangle x:Name="lasso"
Stroke="Blue" StrokeThickness="1" StrokeDashArray="6,2"
StrokeDashOffset="0" / .>

In order for the animation to be smooth you need to set the "To" value to be the size of the dash plus the gap values. So in my example, 8.

Then, when I want the animation to start in my C# code, I set the correct width/height/top/left values for the rectangle and then call the LassoAnimation.Begin function and BAM! Moving dashed border!


.

[Silverlight, C#] Create a simple dashed border

It is simple to set a dashed border of any shape [in my case I was setting a Rectangle border] ... simply set the StrokeDashArray property.

StrokeDashArray = "[Length of dash],[Length of gap], ..."
You can repeat the dash/gap pairs to create different patterns on the same stroke.
XAML:
<. Rectangle ... StrokeDashArray="5.0, 2.0" ./>

C#:
Rectangle lasso = new Rectangle();
...
lasso.StrokeDashArray = new DoubleCollection { 5.0, 2.0 };


.