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 };


.

Tuesday, November 18, 2008

[Silverlight 2] Unable to start debugging...

A co-worker of mine all of the sudden started getting the following error when she was trying to run/debug her Silverlight 2 application [web application with the plug-in being loaded via the auto generated html page]:
Unable to start debugging on the web server. The COM+ registry database detected a system error.
For whatever reason it was the enabled ASP.NET debugger that seemed to be causing this error. Once she unchecked the ASP.NET debugger checkbox found under the properties of the "Web" project [i.e only the "Silverlight" checkbox was checked] then everything started up and debugged smoothly.



.

Wednesday, October 29, 2008

[VS2008] Free Code Metrics Plugin

A few days ago, I was looking around to see if I could find out how to run some basic code metric analysis on my projects. It seems like a few editions of VS2008 [the IDE we're using at work] DOES have some built in code metric evaluation, but only in specific versions of the software. We have a the Professional Edition not the Team Edition... so no go.

But! I found a free VS plugin [thanks to the fine folks at Exact Magic Software] that will add similar functionality!

http://www.exactmagic.com/products/studiotools/index.html

Now, currently the numbers don't mean a whole lot to me since I have nothing to compare them with, but I'm going to start tracking them just to see :)


.

Tuesday, October 28, 2008

[Silverlight] Toolkit Released!

Neat, a new Silverlight toolkit has been released by the MS devs which will add some more components for developers to use and give feedback on.


http://www.codeplex.com/Silverlight

The Silverlight Toolkit is a collection of Silverlight controls, components and utilities made available outside the normal Silverlight release cycle. It adds new functionality quickly for designers and developers, and provides the community an efficient way to help shape product development by contributing ideas and bug reports. This first release includes full source code, unit tests, samples and documentation for 12 new controls covering charting, styling, layout, and user input.



.

Friday, October 24, 2008

[C#] "var" ... Implicitly Typed Variables - When to use?

Alrighty, so during a code review it was brought to my attention that as of C# 3.0 programmers can now use implicit declaration of variables, which was completely contrary to my previous understanding of the language - in that I thought it was solely strongly typed much like C/C++. That is not the case.
Explicit Declaration: int myCount;
Implicit Declaration: var myCount;
Implicit declarations rely on the compiler to chose the best type for you. The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library.

Now while I can see this being handy for many reasons [from what I've read LINQ requires this type of functionality - but I haven't used LINQ yet]... it also troubles me - mostly due to readibility issues if overused. I've done some quick searches and I am not alone in my concerns. I'm just figured I'd list here when *I* think that the use of var can and should be applied for inferring a type.

*** Implicit Usage [My Thoughts] ***
Case 1: If it's required.
Duh... such as with LINQ examples... sometimes you just can't get around it ^^

Case 2: If you are dealing with a very, very, very long type name.
Example:
OhHaiThisIsMyLongClassName myLongClass;
Would become:
var myLongClass;

Case 3: If you Initialize the object on the same line.
Canvas myObj = new Canvas();
Would become:
var myObj = new Canvas(); // <-- We know in the same line what this variable's type is.

Now granted... if the name of your variable does not indicate what it is actually representing, then perhaps there is a programming issue with the naming convention used. I've seen this as an arguement in favor of using "var" - it forces descriptive naming conventions which would in the end actually increase the readibility of a programming.

Really in the end I believe it comes down to personal style - but it's good to keep in mind the pros and cons of using both explicit/implicit typing of variables.


MSDN Documentation on Implicit Typed Variables
Another discussion about when to use "var"

.

Tuesday, October 21, 2008

[Silverlight, C#] Adventures in Accessing Path Data

So I've been stumped for awhile on this, and it seems I was simply misunderstanding something about the Path Syntax used to describe path data, and as I discovered shortly after, there is a limitation in what Silverlight can parse.

Let's start at the beginning. I had a path object, that I took from an example, that looked like this:

[Path Name="shape_path"
Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000"
Width="92.5" Height="57.617"
Data="M137,122 C227,161 168.5,204.5 228.5,159.5" /]

I wanted, in my code behind, to access the Data property so that I could serialize the object into string whenever I wanted to. The problem I was having was that when I tried to access the Data by casting, I was getting an empty collection back.

Essentially PathGeometry g = (PathGeometry)path.Data was giving me an empty collection [Figures] and I had no way to get access to the data. I poked around the Silverlight forums and it seemed like other people were having this issue, and this used to work pre-Beta2, so there was some confusion.

Problem 1: My Misunderstanding of the Types of Path Markup Syntax

As it turns out though, MS never intended a PathGeometry to be accessed in that manner. And here's why [and what I had overlooked]. With Path Markup Syntax, there are actually 2 different types of paths:
StreamGeometry : You use the StreamGeometry mini-language when setting a property of type Geometry, such as the Clip property of a UIElement or the Data property of a Path element. The following example uses attribute syntax to create a StreamGeometry.
[Path Stroke="Black" Fill="Gray"
Data="M 10,100 C 10,300 300,-200 300,100" /]

PathFigureCollection : You use the PathFigureCollection mini-language when setting the Figures property of a PathGeometry. The following example uses a attribute syntax to create a PathFigureCollection for a PathGeometry.
[Path Stroke="Black" Fill="Gray"]
[Path.Data]
[PathGeometry Figures="M 10,100 C 10,300 300,-200 300,100" />]
[/Path.Data]
[/Path]
As you can see from the preceding examples, the two mini-languages are very similar. It's always possible to use a PathGeometry in any situation where you could use a StreamGeometry; so which one should you use? Use a StreamGeometry when you don't need to modify the path after creating it; use a PathGeometry if you do need to modify the path.
In my case, I actually needed to access the Figures collection, so I needed to use the longer notation. In my case, my error was that I had taken an example from somewhere, but it was not the correct syntax for what I ultimately wanted to do.

Now I'm not certain why there is a difference between these two types of paths since they seem so similar, although I imagine a little deeper reading into Geometries would tell me that.

Note: The following link is to documentation for WPF, which is where part of my confusion lay... since support in WPF is different then in Silverlight.
MSDN Documentation on Path Markup Syntax
The correct link is contained in the section "A Good Explanation" at the end of this post.


Problem 2: In Silverlight, Path.Figures Cannot be Parsed using the Mini-Lanugage Syntax

So yay right?!? This should be all fine and dandy! I change my XAML to use the correct Mini-Language as indicated in Problem 1, I go to build/run my application and BAM!

"Invalid attribute value M 10,100 C 10,300 300,-200 300,100 for property Figures. [Line: 5 Position: 27]".

With a little more searching I find a post indicating that:

The PathGeometry.Figures property does not support the path "mini-language" syntax in Silverlight. You have to use the verbose explicit markup to describe those figures in your XAML.

Now I just want to scream... after all that, Silverlight can't even PARSE the mini method of syntax and I need to make sure that the path I'm getting is using the long verbose method :(

Something like this:

[PathGeometry]
[PathGeometry.Figures]
[PathFigure]
[PathFigure.Segments]
[LineSegment Point="150,0"/]
[/PathFigure.Segments]
[/PathFigure]
[/PathGeometry.Figures]
[/PathGeometry]

Blech. How irritating, especially when many examples are given on MSDN in the mini syntax, and from what I've heard the WPF XAMLWriter also outputs the mini syntax.

Anyways, just a heads up, this seems to be the way it is.

Long story short: YOU HAVE TO BE VERBOSE WITH PATHGEOMETRY



A Good Explanation: What is actually supported in Silverlight, and how it works in WPF as well...

First, my hats off to all the people in the Silverlight community that help dummies like me out with issues on forums ^^. Big thanks to Wolf Schmidt (MSFT) who gave me this excellent explanation of what is going on:
PathGeometry.Figures does not support the Path minilanguage/syntax in Silverlight. However, Path.Data DOES support the Path minilanguage/syntax in Silverlight.

In Silverlight, if you use the minilanguage and set Path.Data, you get your intended path and its various parts rendered, but you do NOT get a run-time object tree representation of how that minilanguage was parsed such that you could walk into Figures, Segments, etc. You have to use the verbose form of markup by putting various PathFigure-type object elements under PathGeometry.Figures IF you want discrete run-time "parts" (and for best results, put some "Name" attributes on there so that you don't even need to walk, you can just use FindName).

BTW, in WPF, you also do not get object-tree representation of a path created via the mini-language. The only delta is that Silverlight only supports parsing/processing of the minilanguage on Path.Data whereas WPF supports it for either Path.Data OR PathGeometry.Figures.

PS: the MSDN article you linked two posts above is specifically the WPF version of the Path Markup Syntax information. You need to look at http://msdn.microsoft.com/en-us/library/cc189041(VS.95).aspx which is the Silverlight version. In general, you do have to keep an eye on whether you are looking at a WPF topic or a Silverlight topic when you look at MSDN, because many cases the TOC organization/titling etc. is similar between WPF and Silverlight but the information on the specific pages is often quite different because of the inherent technology differences.

My Silverlight Forum Post

.

Friday, October 10, 2008

[C#] Object Creation with Property Initialization

So a colleague of mine showed me a nice simple way in C# to both create and initialize an object in one step. I thought this was really neat syntax since it both saves lines of code and also saves some execution as the object is initialized with a value instead of a default which is THEN changed.

So something like this:
Rectangle myRec = new Rectangle();
myRec.Width = 50;
myRec.Height = 50;
Can become:
Rectangle myRec = New Rectangle() { Width=50, Height=50 };


There are some restrictions though:
  • Can only initialize properties or fields accessible by the object being initialized.
  • This means that you cannot set attached properties in this manner [ie. Canvas.Top], as these properties can only be set with the SetValue function.
  • The assignments in the initializer is treated the same as assignments to members of the field/property.

See here for a little more
And this msdn page

.

Wednesday, October 1, 2008

[Silverlight] Silverlight Beta 2 RC0 Released

Applications built using this release will work off of the Silverlight 2 RC0 Developer Runtime only. This is not intended for public deployment, as end users will not have a way to install a suitable plug-in to view the application. No existing public versions (released or beta) of Silverlight 1.0 or 2 Beta 2 will be auto-upgraded to this runtime. This is only for developers.

See http://silverlight.net/GetStarted/sl2rc0.aspx
and http://weblogs.asp.net/scottgu/archive/2008/09/25/silverlight-2-release-candidate-now-available.aspx

for more including downloads and breaking changes / new features.

Problems?
After I did the update, when I ran my application in IE I was prompted with the "Install Microsoft Silverlight" button... but how could that be? I just installed the new runtime?

With a little searching I came across this:

A quick fix when updating apps to RC0...if all you get is the "Install Silverlight" button, make sure your object type in your page is changed to
application/x-silverlight-2 instead of applicatiion/x-silverlight-2-b2

And poof! Works!


.

Tuesday, September 23, 2008

[Silverlight, C#] Polyline - Adding Points Does not Seem to Update on UI

I have been working on a small little drawing editor, which would allow the user to draw lines by clicking and dragging. I was using a Polyline to do this, and with every mouse move [or in some cases clicks] I would add a new point to the Polyline Points collection.

This, however, did not seem to work for me. When I added a new point directly into the Points collection, I saw no change in the actual UI indicating that the point had been added.
Polyline myLine = new Polyline();
// Setup visual look of polyline.
myLine.Points.Add(e.getPosition(null));
Not until I removed the element and then re-added it to the parent again could I actually see the new point.

I didn't want to have to remove and re-add to the DOM each time, but I found that I could force the UI to update if I actually changed and then reassigned the PointCollection of the Polyline.
PointCollection ptColl = myLine.Points;
ptColl.Add(e.getPosition(null));
myLine.SetValue(Polyline.PointsProperty, ptColl);
Something about this just doesn't seem right, but maybe I am misunderstanding something key. I am uncertain if this is a bug in beta 2, however, this was my work around for the issue.


.

Tuesday, August 19, 2008

[C#, VS2008 ] One Solution, Mulitple Projects

So I was trying to create one solution which would act as a master build to build the multiple Silverlight projects we have on the go. I ran into slight issues when setting this up, so I thought I'd outline how I did it.

1. Create a "Blank Solution" project.
1a. File -> New Project
1b. Select "Blank Solution" from Other Project Types -> Visual Studio Solutions

2. Force VS2008 to always show the main solution.
This helps when adding existing projects, since for some reason the default in VS2008 is to make the first project you add to the solution the root... making it hard to add multiple projects. *
2a. Go to Tools -> Options [Show all settings] -> Projects and Solutions
2b. Check "Always show solution".

3. Add the desired projects.
3a. Right click the Solution in the solution explorer and Add -> Existing Project.
3b. Browse to select the csproj file from the desired project.
3c. Repeat a&b for all desired projects.

4. Setup any dependencies between the projects.
This step may not be needed if each project already has correct dependencies setup.
4a. Right click the Solution and go to "Project Dependencies"
4b. Select each project from the drop down and select any dependencies if they exist.

That should be it! Build your solution, and all the projects included in the solution should be built in the respective project folders.

* Thanks to Danny-T.co.uk


.

Thursday, August 7, 2008

[Silverlight] What is a .xap File?

So in my travels I bumped into a screencast, and in it, the presenter appended the .zip extension to the end of the .xap file and was able to open up a collection of files by unzipping it! I was like... woooooooah, that's something I didn't know.

What is an .xap file?
The .XAP file is a .zip compressed file that contains the client DLL for the Silverlight application as extra DLLs of assemblies that you are using in your application. This can be your own assemblies of user controls or assemblies that are not part of the Silverlight runtime by default that gets installed on the client.(2)
For more information regarding the files contained in the xap, most notably the AppManifest.xml file, please see the following blogs:
(1)http://pietschsoft.com/post/2008/03/Silverlight-Anatomy-of-an-XAP-file.aspx
(2)http://blogs.msdn.com/katriend/archive/2008/03/16/silverlight-2-structure-of-the-new-xap-file-silverlight-packaged-application.aspx


.

Friday, July 25, 2008

[Silverlight] Adding an image - Why isn't the image showing???

At first all the examples seemed so simple, however, my image was still not showing up when I ran my application.

As it turns out I was placing my image in the incorrect location. I have a Silverlight web application, and as it turns out:
The paths are relative to the .xap file found under the folder [myAppName]/[myAppName]/[myAppNameWeb]/ClientBin.
Like a noob I had been placing them in the folder that contained the .xaml/.cs pages and didn't understand why the images weren't showing...doh!


.

Monday, July 21, 2008

[Silverlight, C#] Animations on Transforms...

So I have been creating a little user control which allows me to dynamically create animations from 'templates', hook them up to elements, run the animation and then kill the animation once it is complete.

I have created a fadeIn/FadeOut quite successfully, however, when trying to animate a shrink/grow I have ran into an issue.

I cannot seem to create an transform animation on an element that does not explicitly have a Group Transform [Scale X / Y in my case] setup on it.

With other properties, like Opacity, you can still animate the property even if it has not been explicitly setup... but this does not seem to be the case with transform properties. I will be doing some forum searching on this tomorrow.


.

Tuesday, July 15, 2008

[Silverlight, C#] WebClient Caching Issue

In my project I am let the user do dynamic loads and saves to the server. During this process I found out that given identical URLS, WebClient [and HTTPBrowserRequest] will retrieve cached copies of the retrieved files. As handy as this is, I couldn't find a way to flag these classes to NOT cache.

Thus, thanks to this forum post, I have created a workaround which involves creating a unique URI.
client.DownloadStringAsync(new Uri(Global.PhpURL + "Graphics/" + fileName + "?FudgeCache=" + DateTime.Now.ToString()));
Fun Stuff. Maybe it will get fixed later, since from what I've read you can flag no cache in WPF.

.

Friday, July 11, 2008

[Silverlight, C#] TextBox Fuuuuuuuuun!

So this afternoon I dove into the wonderful world of TextBoxes, as I now wanted to add the ability for people to add text to my WYSIWYG drag/drop app. And boy oh boy does this look fun [*rollseyes*]. Tabstops and focus issues oh my!

Giving Focus to a TextBox Programatically

While I thought this was as easy as calling the Focus() function, but as it turns out, you also have to make sure that the IsTabStop property is true as well.
this.mytextbox.IsTabStop = true;
this.mytextbox.Focus();

Focus Puts the Caret in the TextBox, but Keystrokes are not captured
/shrug

[Silverlight, C#] Determining Coords with respect to the application

So I am working with multiple user controls, and I have elements in those user controls that I want to drag/drop them seamlessly between without the user knowing about the fact that the elements were being passed back and forth between user controls.

Originally I had been recursively adding together the Top/Left values all the way up to the "root"... however, when I introduced the user controls, it became tricky. Each user control has it's own "root"... so my recursive function would stop at the user control root, and thus my Top/Left values were now only relative to the user control root! Doh!

After digging for awhile, I came across a wonderfully handy little function:
UIElement.TransformToVisual
Returns a transform object that can be used to transform coordinates from the UIElement to the specified object.

With this I made a function that would return me a Point containing the offset X/Y values that would give me the relative coord change needed to move to the new coord space of the wrt element.
/// < summary >
/// Returns the Point that can translate the desired element w.r.t to another element.
/// < /summary >
public static Point getVisualCoordsWRT(UIElement findMe, UIElement wrtMe)
{
  GeneralTransform gt = findMe.TransformToVisual(wrtMe);
  return gt.Transform(new Point(0,0));
}

So to get coords wrt the application I could do this:
Point offset = getVisualCoordsWRT(controlElement, Application.Current.RootVisual);


Thanks to this Silverlight forum post.

.

Thursday, July 3, 2008

[Silverlight, C#] Creating Attached "Collection" Properties

Sorry for a lengthy delay in posting... it's been a frustrating past few weeks. Anyhoot - FINALLY I have a solution for a problem that has been plaguing me for awhile now.

What I wanted to do:
I wanted to be able to have a collection of random elements [in my case, a collection of Link elements [my own class] and be able to associate that collection with ANY element in my XAML DOM... not just Panel elements - Rectangles, Paths etc...

Essentially I wanted my code to look like this [where local is the access to my namespace]:
< Rectangle x:Name="testingRectangle" >
  < local:LinkManager.Links >
    < local:LinkCollection>
      < local:Link ObjRef="sdf" / >
    < / local:LinkCollection>
   < / local:LinkManager.Links >
< / Rectangle >

Creating the Link Class:
I spent a ton of time trying to figure out how to get the ObjRef property to be implemented correctly so that it could be accessible in syntax to how I showed in teh above XAML... turns out it's dead simple. No need to register AttachedProperties or DependancyProperties and whatever the heck else I was grasping at straws to do. It's as simple as this:
public class Link
{
 private String _ObjRef;
 public String ObjRef
 {
  get { return _ObjRef; }
  set { _ObjRef = value; }
 }
}


Adding the Attached Collection:
In order to do this, I created a class which would act as the LinkCollection, which derived from the ObservableCollection generic.
public class LinkCollection : ObservableCollection < Link > { }


Creating the Attached Property:
Now I needed to create a class which would essentially be a 'hook' which would allow me to create an attached property which all other elements could access. I called this LinkManager, and it only consists of the registering a attached property [giving access to the newly created LinkCollection].
public class LinkManager
{
 public static readonly DependencyProperty LinksProperty =   DependencyProperty.RegisterAttached(
   "Links",
   typeof(LinkCollection),
   typeof(LinkManager),
   null);

 // Accessors for the dependency property:
 public static LinkCollection GetLinks(DependencyObject obj)
 {
  return (LinkCollection)obj.GetValue(LinksProperty);
 }
 public static void SetLinks(DependencyObject obj, LinkCollection value)
 {
  obj.SetValue(LinksProperty, value);
 }
}

Accessing the Collection in Code Behind:
Then it was easy enough to grab the collection given the above XAML!
LinkCollection testCollection = this.testingRectangle.GetValue(LinkManager.LinksProperty) as LinkCollection;


And that's it! Now I can attach a collection of Links to whatever XAML element I want via AttachedProperties!

Huge thanks to dcstraw on the Silverlight forums I posted on ;)
http://silverlight.net/forums/p/19884/69373.aspx#69373

Cleaning up the code a little:

I was hoping to do something like this post talks about, which would remove one of the levels of XAML code... but for some reason I cannot get it to work properly.


.

Friday, June 20, 2008

[Silverlight, C#] User Controls and Namespaces

In working with my user controls I started creating elements dynamically which were then moved back and forth from user control to user control depending on the actions the user was taking. I then ran into some naming problems: I had a function that would check for the existence of a name before I added the element to the DOM, however, I was getting some unexpected results.

So then I asked myself the question... how is this even working? I have multiple copies of a user control, how come I am not seeing naming convention issues when I use the same control twice in my application?

I did a little test regarding User Controls and the names of objects inside them and determined: User Controls create an implicit new namespace so that the elements within it may continue to be named the same. This means you cannot 'find' an element name that does not DIRECTLY belong to the user control namespace you are searching in.

Check out the screen shot of the application I whipped up, and hopefully it will make sense.

.

Monday, June 16, 2008

[C#, Silverlight] Access to Resources

A little background... I want to be able to load up a XAML element from a file that may or may not contain an animation associated with its resources, and then start the animation when I mouseover this newly created element.

Here is exactly what I *want* to do:
  • Load up a snippet of XAML code [read from a xaml file retrieved from my server] via XAMLReader.Load(). This XAML object may contain a storyboard in it's resources:

    • < Rectangle name="myRect" fill="Blue" width="50" height="20">
        
          < Storyboard x:Name="myRect_Storyboard" >
            < DoubleAnimation Storyboard.TargetName="myRect" ... / >
          < /Storyboard >
        < /Rectangle.Resources >

  • Call the Begin() function for the storyboard when I load up the XAML snippet.
  • Here is my problem though... I do not know the NAME of the storyboard when loading up the XAML snippet, or if a storyboard even exists.

A few notes:
  • As of Silverlight 1.1... elements in a ResourceDictionary [including Storyboard] must have their x:Name set.
  • Each resource property element within each ResourceDictionary must have a unique value for the x:key [name?], which serves as the unique key when values are retrieved from the ResourceDictionary.
  • We can set the "Name" property... but can we set the "x:Name" property in code behind?
  • XAML syntax does not include an element for the ResourceDictionary class. This is an example of XAML implicit collection syntax; a tag representing the collection element can be omitted. The elements that are added as items to the collection are specified as child elements of a property element of a property whose underlying type supports a collection Add method. [MSDN]
  • Every framework-level element (FrameworkElement or FrameworkContentElement) has a Resources property, which is the property that contains the resources (as a ResourceDictionary) that a resource defines. You can define resources on any element. However, resources are most often defined on the root element, which is Page in the example. [Taken from MSDN.]
  • As of Silverlight beta 2, the Application.ResourcesProperty is private.

I'll come back to this later... this was just a dumping ground for things I have found so far.

EDIT: I was trying to enumerate through the ResourceDictionary [FrameworkElement.Resources], however in Beta 2 this was always showing as 0 after the XAML snippet was loaded.

Turns out - it's a bug! So I'm just going to have to wait until it's solved unless I can think of some other way to get access to the resources without knowing their names.

Thursday, June 12, 2008

[C#] Custom User Control Constructors [No Arguments]

So I was playing around with the new custom user controls I created for my ProgressBar etc... and I noticed that when I was trying to inject them into another XAML page that is in my project that the intellisense wasn't picking it up. It was like the control was not valid even though I was using the correct namespace, and could see my OTHER custom controls.

I started playing around and I noticed that I had ONE constructor for the control, and it took one parameter [I was setting a property or something with this parameter]. When I removed the argument from the function call [ie. public ProgressBar() {...}] - BAM - I could see the control via intellisense!

Again, this may be common knowledge, but it leads me to think that:
  • All custom user controls MUST contain a constructor with no arguments?
I'm guessing this is due to how inheritance is implemented, and had I REALLY thought about this earlier, I should have known this to be the case.

[Silverlight B2, C#] Custom User Controls "Overlap" in StackPanel...???

Ok, so I'm going to put money on the fact that I am doing something wrong... but I have no clue what. Here's the run down:
  • I created a User Control for a ProgressBar
    • XAML consists of a Canvas, border Rectangle, fill Rectangle, and a TextBlock.
    • C# code simply allows for the "percentComplete" which will change the width of the fill bar and the text accordingly. It's really rather simple.
  • I created a User Control for a ProgressArea
    • XAML consists of a StackPanel that will contain one or more ProgressBars.
    • C# code has an "AddBar" function which will create a new ProgressBar and then add it into the StackPanel.
Seems simple... however, when I add more then one ProgressBar they "overlap" each other. It's like the StackPanel has no idea about the width/height of each control. I know that they are overlapping because if I set the margin to something like "20,20,0,0" I can SEE both of them.

When I add multiple standard controls to the StackPanel [like TextBlock] they stack fine. Obviously I am not setting something correctly in my custom control... just have no idea what. Once again my google search has turned up nothing.

So if anyone is ACTUALLY reading this, and knows what's up... PLEASE let me know!!! I will like love you forEVAR :)


EDIT: Ok so... I'm not certain exactly what happened. I was playing around with getting around this problem by setting the margin of each ProgressBar to be just a smidge bigger then the height of the bar. And after setting it and then removing it... the stack panel seems to work fine now. My controls are stacking on top of each other just fine WITHOUT my margin setting.

/Shrug. No idea. But I'm not going to complain.


.

Tuesday, June 10, 2008

[Silverlight B2] No more "MouseLeftButtonDown" event on Button?

Whee! More problems!

I have been using the "MouseLeftButtonDown" event to register all of my events that may pertain to a click. I've been doing this in practice because some of my objects differentiate between clicking down and clicking up [like for drag/drop]... so I just always extended this into my other object's event handlers... like buttons.

So before I had something like this:

[Button x:Name="Group" FontFamily="Arial" Content="Group" MouseLeftButtonDown="Group_MouseLeftButtonDown"]

But when Beta 2.0 dropped, that event no longer seemed to fire or was not getting registered correctly... I'm not actually sure since I couldn't find any documentation in the Breaking Changes page. I imagine it is tied to the changes made to event bubbling in 2.0.

To fix this I simply needed to change my buttons to use Click:

[Button x:Name="Group" FontFamily="Arial" Content="Group" Click="Group_Click" Margin="2"]

I still think that as an application designer we should be able to apply different event handlers to both the mousedown and mouseup events on a button, so maybe a solution will present itself in time. For now though, it was acceptable for me to simple switch to registering the Click event.

I just wanted to blog this as being an issue for me, in case anyone else ran into the same thing - or had some more info.

NOTE
Through the intellisense on VS2008, it came to my attention that:
  • Click is a RoutedEventHandler
  • MouseLeftButtonDown/Up events are MouseButtonEventHandler(s)
  • Each have their own respective argument types
I didn't realize there was a difference between mouseup/down and click... and perhaps this could point to part of the problem I was having.

NOTE
This blog gives a decent explanation of the bubbling changes that have occurred.

.

Converting from Silverlight Beta 1 to Beta 2

As usual, the transition from one beta to the next brings breaking changes... just going to list the ones I had here, and how I got around them:

SetValue Only Accepts the Correct Types (No Conversions)
Before I was passing in Strings for colors when manually creating my xaml elements, or I was using strings for some other properties where I shouldn't have been.
For example:
Beta1: myRect.setValue(Rectangle.FillProperty, "red");
Beta 1: myRect.setValue(Rectangle.StrokeThicknessProperty, "2");

This was nice because all the conversion to a SolidColorBrush was done for me... but alas they caught on to my laziness. So now I must do something like this:
Beta 2: myRect.setValue(Rectangle.FillProperty, new SolidColorBrush(Colors.Red);
Beta 2: myRect.setValue(Rectangle.StrokeThicknessProperty, 2.0);

I imagine I will also run into some issues when I need to convert from a HEX color, but I'll cross that bridge when I get there.


WebClient and HttpWebRequest Changes
This one really eluded me. This manifested in my code in the following way: I was using HttpWebRequest to get a xaml string directly from a file on my server, and then I was loading that xaml via xamlReader.load... BUT... I was now getting a Invalid cross-thread access" [System.UnauthorizedAccessException] exception.

Loading the EXACT same xaml from the page_loaded function worked fine... what the heck? From the advice of my project manager, I checked the Thread.CurrentThread.ManagedThreadId [System.Threading] of both the page_loaded and my httpWebRequest callback function and BAM... they are now in different threads.

Turns out there were a few things I was unaware of with Beta 2:
  • HttpWebRequest delegates were changed to return on a background thread.

  • HttpWebRequest is callable on a background thread

Also, what I wasn't aware of was this [which given the HttpWebRequest changes was brought to my attention]:
Solution?
Following the example shown on the Breaking Changes documentation I switched to using WebClient, which is now a much more robust class in beta 2.

My project manager also suggested I check out creating my own BackgroundWorker threads which would do any consuming processing I may need in the future, and then do a callback to my main thread when completed with the processed data that the main thread could use to create the desired XAML. I'm guessing BackgroundWorker will be my next blog post XD


More to follow I imagine...

Monday, June 9, 2008

Silverlight 2 Beta 2 is out!

Get it here.

1. Uninstall your old SDK and VS2008 toolkit.
2. Install Beta 2 via the silverlight_chainer file.
3. Checkout the Breaking changes from Beta 1 to Beta 2:
Download: Beta 2 Documentation
or
Online: On MSDN

BAM

[C#] Creating Custom Attached Properties

I'd been looking into creating custom attached properties to xaml elements so that I could store relative information regarding our "Object Linking" that will need to be implemented in my project. The concept was a little muddled to me, and I came close to getting it working last Friday, I was just missing a key step!

This is the HOW-TO article that helped me get it all together this morning:
Attached-Properties-in-Silverlight

Thursday, June 5, 2008

[WPF] Preview vs. Non-Preview Events

So in my reading travels today I started looking up animations, which took me to triggers, which took me to event handling, and I then bumped into the concept of preview vs. non-preview events [the mind is a wonderful thing]. This is particularly interesting to me since I have been using event handling in my current project, but don't fully understand how the model works.

So first of all... some definitions yoinked from MS because they make more sense then I ever could:

Taken from MSDN
Routed Event: A routed event is a type of event that can invoke handlers on multiple listeners in an element tree, rather than just on the object that raised the event.

A typical WPF application contains many elements. Whether created in code or declared in XAML, these elements exist in an element tree relationship to each other. The event route can travel in one of two directions depending on the event definition, but generally the route travels from the source element and then "bubbles" upward through the element tree until it reaches the element tree root (typically a page or a window). This bubbling concept might be familiar to you if you have worked with the DHTML object model previously.

Routing Strategies:

  • Bubbling: Event handlers on the event source are invoked. The routed event then routes to successive parent elements until reaching the element tree root. Most routed events use the bubbling routing strategy. Bubbling routed events are generally used to report input or state changes from distinct controls or other UI elements.
  • Direct: Only the source element itself is given the opportunity to invoke handlers in response. This is analogous to the "routing" that Windows Forms uses for events. However, unlike a standard CLR event, direct routed events support class handling (class handling is explained in an upcoming section) and can be used by EventSetter and EventTrigger.

  • Tunneling: Initially, event handlers at the element tree root are invoked. The routed event then travels a route through successive child elements along the route, towards the node element that is the routed event source (the element that raised the routed event). Tunneling routed events are often used or handled as part of the compositing for a control, such that events from composite parts can be deliberately suppressed or replaced by events that are specific to the complete control. Input events provided in WPF often come implemented as a tunneling/bubbling pair. Tunneling events are also sometimes referred to as Preview events, because of a naming convention that is used for the pairs.



Using routed events properly means that you can setup a common event listener to catch multiple events triggered from multiple objects. This concept is probably not new, but I found it interesting.
Routed event listeners and routed event sources do not need to share a common event in their hierarchy. Any UIElement or ContentElement can be an event listener for any routed event. Therefore, you can use the full set of routed events available throughout the working API set as a conceptual "interface" whereby disparate elements in the application can exchange event information. This "interface" concept for routed events is particularly applicable for input events.
So for example you can setup something like this:

< StackPanel Background="LightGray"
Orientation="Horizontal"
Button.Click="CommonClickHandler" >
< Button Name="YesButton" Width="Auto" >Yes
< Button Name="NoButton" Width="Auto" >No
< Button Name="CancelButton" Width="Auto" >Cancel
< /StackPanel >


and then use one handler like this:

private void CommonClickHandler(object sender, RoutedEventArgs e)
{
FrameworkElement feSource = e.Source as FrameworkElement;
switch (feSource.Name)
{
case "YesButton":
// do something here ...
break;
case "NoButton":
// do something ...
break;
case "CancelButton":
// do something ...
break;
}
e.Handled=true;
}
Routed events can also be used to communicate through the element tree, because the event data for the event is perpetuated to each element in the route. One element could change something in the event data, and that change would be available to the next element in the route.

FOR CRYING OUT LOUD... WHAT DOES THIS HAVE TO DO WITH PREVIEW EVENTS???
Gosh, weren't you reading? Tunneling events are referred to as "Preview" events. This is due to the fact that in WPF the naming convention to call such events are prefixed with the word Preview. Preview events are fired in the tunneling phase, and give a 'preview' of the state of the objects - however note that you cannot actually 'handle' the event in this phase, and thus you cannot set the event as being handled.

All other non-preview events are just as we expect. They are triggered in the bubbling phase and allow you to properly set the event as being handled.

Silverlight Note:
I am uncertain if Silverlight supports preview events yet. From the documentation I have seen, these events are prefixed with "Preview" [like "PreviewKeyDown" vs. "KeyDown"] and I cannot seem to access them via the VS2008 intellisense.

Why Use Preview Events?:
Use preview events if you wish to log some logic before any event handling occurs.
This forum post talks a little about the purpose of Preview Events.

Wednesday, June 4, 2008

[VS2008, Silverlight] "The project type is not supported by this installation"

So I spent the last 5 hours trying to get my VS2008 [which I had to do a re installation on] to recognize and open my silverlight projects. After uninstalling and reinstalling I was faced with the error message when trying to open my Silverlight project:
"The project type is not supported by this installation"
I figured that there was an issue with the Beta Toolkit for Visual Studio 2008, so I began my journey of uninstalling those components, reinstalling them, running into issues, hacking the registry, and cursing a lot. After all this was said and done... I reinstalled the Tools only to get the exact same error again.

Searching this error I found a webpage that instructed me to do the following:

Launch a command window, navigate to C:\Program Files\Microsoft Visual Studio x\Common7\IDE (where x is the version number) and run:

devenv /setup
That's it. That's all. Works perfect now. Thank you Andrew Gunn... I love you.

ps. I was curious about devenv /setup so I looked it up... it appears to merge menus, toolbars, command groups etc from all packages available. Not exactly sure what this means FULLY, but I imagine it tells VS2008 about all the packages [including the Silverlight package] that are available to it and that somehow in my re installation this package was missed.

/shrug.

Tuesday, June 3, 2008

[C#, WPF] Dependency Properties, Objects and Attached Properties [Oh my!]

Ok wow... I opened up a can of worms looking up "attached properties" this morning. I need another coffee. Here goes though - it appears that WPF introduced a few new key concepts, including Dependency Properties [and thus Dependency Objects, and Attached Properties].

Dependency Properties
Dependency Properties [called DPs from now on because I am lazy] were introduced throughout the WPF platform to help enable styling, databinding, animation and more. Quite literally, a DP depends on multiple different providers to determine it's value at any given point in time. The main reason behind this structure is to allow for rich functionality to be enabled directly from the markup [XAML] instead of relying on any procedural code.

Because of this 'dynamic determination of values', the WPF infrastructure must be setup to know and deal with DPs correctly. DPs have a very specific implementation structure that must be adhered to if one wishes to create a DP. They have a special naming convention ( [propertyName]Property --> MyDPProperty) and are public static. They must be registered so that WPF knows how to perform the callbacks when specific events occur on the property. I'm not going to go into the details of registering a DP as it is a little more in depth then I'd like to go today, but please see my links below for more info.

Excellent Reference for DPs [en.csharp-online.net]


Dependency Objects
If creating class that you wish to add DPs to, you must derive from DependencyObject so that WPF knows to enable it's property system services on it. The property system service is what WPF uses to calculate the value of a dependency property based on the multiple providers that may exist for a DP.

My focus for today is more on the DPs and attached properties, so I will leave any explaination about DO's short... namely because *I* haven't really read up on them in much detail ;)

MSDN DependencyObject
Support for multiple providers


Attached Properties
Finally... this is where I started. An Attached Property [AP] is a special form of a DP that can be attached to arbitrary objects that may not actually support the given property. Sounds weird right? It makes more sense when you look at the use of these properties to give styles to an element and it's associated children via "property value inheritance".

The term property value inheritance (or property inheritance for short) doesn't refer to traditional object oriented class-based inheritance, but rather the
flowing of property values down the element tree.

So in other words, if you set a property in a parent element, the children will also recieve the same value unless specifically specified in the child element. But what happens if you wish to set up this property inheritance on a parent object that doesn't natively support that property? Say you have a StackPanel and you want all children of the StackPanel to have the same FontSize? This is where attached properties because very useful.

< StackPanel TextElement.FontSize="22" >
< Button >Button1 </Button >
< Button >Button2 </Button >
< Button >Button3 </Button >
</ StackPanel >


All buttons will have FontSize of 22 since none have been overridden.

For this to work, an attached property provider must be used [in this case TextElement], which provides access to the get/set accessors for the attached property. Calls to the Get/SetValue methods are actually applied on the passed-in DependancyObject, rather then the current instance. [Ie. on TextElement, not on StackPanel].

The all too familiar property of Canvas.Left/Top on elements such as a Rectangle [if I am understanding this correctly] is actually an attached property then! This makes more sense now looking at how things are syntactically set up.

Again, there are more complexities with attached properties to go into but I am not going that deep today. Need to let all this sink in first :)

Attached Properties [en.csharp-online.net]

Monday, June 2, 2008

[C#] Using TooltipService

NOTE: As of Silverlight 2 Beta 2, this seems to be borked. Not sure why yet... I'll have a look later.

Today I was trying to add a simple tooltip to a bunch of small Canvas' in my Silverlight project. After a little digging I found that
  • (a) there is a .NET class called Tooltip which does this functionality for me and
  • (b) many controls lack a ToolTip property [such as TextBox, TextBlock, Canvas etc...]
To add a ToolTip to these controls, we are able to use the ToolTip attached property via ToolTipService. I am unfamiliar with attached properties, and I will be going over them in detail soon, however, for now I'm just going to drone on about using the ToolTipService in C# since it took me a little digging to find any kind of example [most were examples in XAML only].
  // Create a Tooltip
ToolTip nameTip = new ToolTip();

// Set the content [here I use text, but apparently it can be more complex]
nameTip.Content = "Testing ToolTipService";

// Use ToolTipService to attach the ToolTip to my Canvas.
ToolTipService.SetToolTip(myCanvas, nameTip);
Note, you may need to add the System.Windows.Controls reference to your project for this to work... I can't recall if that assembly is added by default when you create a project in VS2008.

ToolTipService Documentation

[Silverlight] Events on a Canvas with no set background color...

It's funny, both myself and another girl at work bumped into this same issue today while working on unrelated projects.

It seems that if you wish to set up events on a Canvas then you MUST set the Background property for the event to trigger when clicking ANYWHERE on the Canvas. If you do not setup a background, then the only time the event will be registered on the Canvas is if the user happens to click on a visible child of that Canvas.

By default the Canvas.Background property is set to null. Now, I imagine that this has the possibility to be rendered differently depending on what is interpreting the xaml. I noted that you can set the background to "transparent" [which is different then null], and while the Canvas will look identical to the default null value, the events will be correctly registered when you click anywhere within the canvas.

Canvas eventWrap = new Canvas();
eventWrap.Background = new SolidColorBrush(Colors.Transparent);
eventWrap.MouseEnter += new MouseEventHandler(showTooltip);
eventWrap.MouseLeave += new MouseEventHandler(hideTooltip);
eventWrap.Children.Add(myWeirdShapedPolygon);
This makes sense when you think about it, since it may be the case that you do not want the events to trigger when mousing over 'unused' portions of the canvas space. I just thought it was interesting to note that ((Background == null) != (Background == Colors.Transparent))




Friday, May 30, 2008

[XAML] Using Width and Height of a Polygon/Polyline

So for awhile I was bashing my head against my desk trying to figure out how to get/set the height/width of a polygon so that I could perform a stretch type action on the element.

Originally I was not setting the width and height properties, and I was trying to find the bounding box of the item by iterating through each point in its point collection and then determining the width and height from there... which seemed to work, but if I tried to then change the width/height attribute directly the whole thing would bork on me. The width and height were returning NAN.

Turns out what I needed to do was set the Stretch property to "Fill" and then set the width and height accordingly.
Stretch [Fill] = The Shape object's contents are stretched to fill its layout space. Aspect ratio is not preserved.
Layout space = Is the amount of space the Shape is allocated by the layout system, because of either an explicit Width and Height setting or because of its HorizontalAlignment and VerticalAlignment settings.

polygon
name="PolyStretch"
points="-10,-1 200,200, -100,10"
fill="Blue"
width="50"
height="50"
stretch="Fill"
This means that I could not 'clip' a polygon while still using the stretch property... which makes sense, but my case I want changes to the layout space [height/width] to effect the points inside giving me the stretch operation - so everything is a-ok!

MSDN Reference

Tuesday, May 27, 2008

[Silverlight] XamlParseException when setting IsChecked flag in XAML

Alrighty, today I made a basic debug log to dump messages and test timings to. I wanted to setup a checkbox on my application to toggle the visibility [and to toggle off the logging/testing] of this debug panel... but when doing so I kept running into the exception:
A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in System.Windows.dll

Additional information: AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 33 Position: 206]

My checkbox had two event handlers set up on them... one for Checked and one for Unchecked. These functions would toggle the visibility of the debug log. THIS is what I had done wrong however... I had also set in my XAML the IsChecked flag equal to true.

What this essentially did then, was call the event handler I had setup for Checked. Given that this event call was actually made before the entire page was loaded, I received an error when trying to toggle the visibility of the debug log which was not actually loaded into the DOM yet!

Thus here is my recommendation:
Never EVER set the IsChecked flag of a checkbox element in the XAML code itself, since there is a good chance that whatever elements you wish to command are not properly injected into the DOM yet.

After the page is initialized then add the line "[checkboxname].IsChecked = true" in the code behind... as this will guarantee that the DOM has been fully structured.

Monday, May 26, 2008

[C#] Accessors - get and set cleanliness

While looking at some example code, I bumped into some syntax that looked like a shorthand for declaring get and set methods for a given property - and I thought "well hey, isn't that cool".

Turns out that in C#, this is exactly the case...

"The accessor of a property contains the executable statements associated with getting (reading or computing) or setting (writing) the property. The accessor declarations can contain a get accessor, a set accessor, or both."

Instead of writing something like this which I do all the time:
class myClass
{
private int myProp;
public void getMyProp() { return myProp; }
public void setMyProp(int newProp) { myProp = newProp; }
}
We can do this in C#:
class myClass
{
private int myProp;
pubic int MyProp
{
get { return myProp; }
set { myProp = value; }
}
}
This is a little cleaner and allows us to access the get and set functionality in a very straight forward manner:
  • int whee = myClassInstance.myProp;
    • instead of --> int whee = myClassInstance.getMyProp();
  • myClassInstance.myProp = 22
    • instead of --> myClassInstance.setMyProp(22);
A few things to note:
  • Both the private property, and the public property containing the accessor functions may have very similar names, but do not confuse them.
  • May contain only set [write], only get [read] or both [read/write].
  • The 'value' seen in the set accessor is a C# keyword. It is a free variable that is created by the complier, and no other variables within the set accessor may share that name [duh].
  • There's more to it when talking about inheritance and abstract classes, but perhaps I'll save that for another day.
  • Can also be done for a public member variable, although to me this seems a little silly since you can directly access a public variable anyways. I just added this to show that the syntax was possible.
    class myClass
    {
    public myPublicProp
    {
    get { return myPublicProp; }
    set { myPublicProp = value; }
    }
    }

MSDN Documentation

Friday, May 23, 2008

I hate blogspots WYSIWYG

I apologize for the messy layout of the below posts. I seem to be having disagreements with the WYSIWYG editor, namely when trying to add <> symbols. Flipping back and forth between HTML and COMPOSE view will seemingly change these for me, even after I've hard coded them in the HTML view as "&lt" and "&gt".

Thursday, May 22, 2008

[C#] Nullable Types

I bumped into this in my web travels today: Nullable types. Introduced in the 2.0 .NET framework was the ability to represent the normal range of values for a given value type PLUS the null value.

Nullable types can only be VALUE types [including structs]. It cannot be applied to reference types. Syntactically they look as follows:
  • T? // Is actually shorthand for...
  • System.Nullable // A struct - see below for its properties.


Ex. int? or System.Nullable

The nullable struct brings with it two readonly properties:
  • HasValue: Returns true if the variable contains a value, and false if null.
    • ex. Can use (x.HasValue) or (x != null) pretty much interchangeably.
  • Value: Returns the value if one is assigned or throws an InvalidOperationException if not assigned. Often this function is used to help cast a nullable type to a non nullable type.
ex.
// Correct
int? iNull = null;

// Will not compile
int notNull = iNull;

// Will compile, but exc thrown if null.
int notNull2 = iNull.Value;


When using operators on nullable values, the result will be a null if any of the operands are null. When comparing nullables, if one of the values is null then the comparison is always FALSE.

Often used with Nullable types is the ?? operator. It returns the left-hand operand if it is not null, or else it returns the right operand.

int? iNull = null; int iNull2 = null;

// notNull will receive the value -1.
int notNull = iNull ?? -1;

// Can use the ?? multiple times...
int notNull2 = iNull ?? iNull2 ?? -1;


If using bool? then the variable may not be used in conditionals like if, or for. The code will not compile.

Reference MSDN

Wednesday, May 21, 2008

[C#] More on string concatenation - String.Join

After yesterday's post about "+=" vs StringBuilder, I did a little more looking around on the topic of string concatenation. It appears that if you can get the strings you wish to concatenate into an array then the String.Join(string, string[], int, int) method is actually faster then the StringBuilder.Append method.
public static string Join(
string separator,
string[] value,
int startIndex,
int count
)
Now, in my case, I have a dynamic number of strings I am concatenating together - so using String.Join is a little trickier because I seemingly have to create a List first and then copy over to a String[] before I can use the String.Join method.

My Test - String.Join vs. StringBuilder.Append vs. "+="
I was curious about this, wondering if those intermediate steps would slow things down enough to make String.Join worse than StringBuilder in efficiency... so I wrote up a small little test with timing:
...
int[] numStrings = { 100, 1000, 10000, 20000, 30000 };
foreach (int num in numStrings)
{
output += "*** NUM STRINGS = " + num.ToString() + " ***\r\n";

//---------------------------------
// String.Join
//---------------------------------
start = DateTime.Now;
poo = new List();
for (int i = 0; i < num; i++)
{
poo.Add("poo");
}
newArr = new String[poo.Count];
poo.CopyTo(newArr);
allPoo = String.Join(" ", newArr);
end = DateTime.Now;
diff = end.Subtract(start);
//---------------------------------
start = DateTime.Now;
output += "String.Join: " + diff.ToString() + "\r\n";

//---------------------------------
// StringBuilder.Append
//---------------------------------
newBuilder = new System.Text.StringBuilder();
for (int i = 0; i < num; i++)
{
newBuilder.Append("poo ");
}
end = DateTime.Now;
diff = end.Subtract(start);
//---------------------------------
start = DateTime.Now;
output += "StringBuilder: " + diff.ToString() + "\r\n";

//---------------------------------
// +=
//---------------------------------
myString = "";
for (int i = 0; i < num; i++)
{
myString += "poo ";
}
end = DateTime.Now;
diff = end.Subtract(start);
//---------------------------------
start = DateTime.Now;
output += "+=: " + diff.ToString() + "\r\n";
}
this.oam.addMessage(output);

To which the output was:
*** NUM STRINGS = 100 ***
String.Join: 00:00:00.2031224
StringBuilder: 00:00:00
=: 00:00:00

*** NUM STRINGS = 1000 ***
String.Join: 00:00:00
StringBuilder: 00:00:00
=: 00:00:00.0156248

*** NUM STRINGS = 10000 ***
String.Join: 00:00:00.0156248
StringBuilder: 00:00:00
=: 00:00:01.1249856

*** NUM STRINGS = 20000 ***
String.Join: 00:00:00.0156248
StringBuilder: 00:00:00
=: 00:00:06.5311664

*** NUM STRINGS = 30000 ***
String.Join: 00:00:00.0156248
StringBuilder: 00:00:00.0156248
=: 00:00:16.1404184

So as you can see in this test:
  • StringBuilder.Append only becomes more efficient then String.Join after 1000 strings, although even then the two seem very close in efficiency.
  • "+=" is the least efficient of the group, although it really only becomes noticeable after 1000 strings
My Conclusions
  • I'll probably try to use String.Join where ever possible when doing my large string concatenations, even if I have to place all the strings into a List before I use the method.





Tuesday, May 20, 2008

[C#] Efficient String Concatenation - "+=" vs StringBuilder

Again, in my short C# travels, I find myself very very often doing dynamic string concatenations. One major task I have tried to do is create a basic serialization function for XAML elements, so that I can store/save a XAML element to the server in my project. I thus end up doing many, many string concatenations.

Using "+=" to Concat
So often I end up doing this...:

String newStr = "";
if ([prop] != null) { newStr += "[prop]= " + obj.getValue([prop]).toString(); }

...for many, many properties. When actually compiled, every time the "+=" concatenation is used, an entirely new string must be created to hold the 'new' complete string. This can become very inefficient and slow if you do a large number of such string concats.


Using StringBuilder

What I didn't know about, was the StringBuilder class. Found under the System.Text library, StringBuilder maintains an internal buffer to which [via the function StringBuilder.Append()] will append to; thus a new string will not be created every time an append occurs. If the internal buffer is exceeded THEN a new buffer size will be allocated.

Thus the usage of StringBuilder *CAN* be more efficient then using "+=". Note that more overhead is needed to create and manage the StringBuilder object, so in all cases, StringBuilder will *NOT* be absolutely more efficient. It really depends on the size of the strings and the frequency of the concats.

General Rule of Thumb
  • If the concats can fit into one statement [or only a few statements], then the "+=" is probably the safest route to take.
  • If you have multiple long, or a dynamic amount of string concats, then StringBuilder may be able to increase efficiency.

Reference: www.yoda.archsys.com

Friday, May 16, 2008

[C#] More about Typecasting with 'as' and 'is'

Taken from this CodeGuru article I found by Jay Miller

Often in my programming experiences with C# I want to check if an object is a specific type without throwing a code stopping exception. So I end up writing something very similar to this:

if (myObject.GetType().ToString().Name == "Canvas")
{
// Wicked code goes here.
}

or

Canvas myCanvas = myObject as Canvas; // If invalid typecast this will return null.
if (myCanvas != null)
{
// Wicked code goes here.
}

I've found a slightly cleaner way to accomplish this:

Canvas myCanvas = myObject as Canvas;
if (myCanvas is Canvas)
{
// Wicked code goes here.
}

The change is subtle, but I think that it makes this comparison much more clear and easy to read. Also, according to the referenced article, this comparison via 'is' is slightly more efficient then comparing against null.

Thursday, May 15, 2008

[C#] Parameter Passing - "ref" and "out"

Before I get into parameter passing...

There are two different types in C#
1) Value-Types [http://msdn2.microsoft.com/en-us/library/s1ax56ch(VS.71).aspx]
- Structs
* Built in --> Numeric Types [int, double etc...], Bool.
* User defined
- Enums
- Unlike reference types, it is not possible for a value type to contain the null value.
2) Reference-Types [http://msdn2.microsoft.com/en-us/library/490f96s2(VS.71).aspx <-- seems to be broken]
- class, delegate, interface, object, string.
Parameter Passing
All value-type parameters are what we call "pass by value" and all changes made to that value in the function will have no affect on the original data.
All reference-type parameters are "pass by reference" and all changes made to it will be reflected in the original.
If you want to force a parameter to be pass by reference then we use the "ref" or "out" keyword.
Differences Between "ref" and "out"
"out": an out parameter of an array type must be assigned before it is used; that is, it must be assigned by the callee.
For example:
public static void MyMethod(out int[] arr)
{
arr = new int[10]; // definite assignment of arr
}
C#
"ref": a ref parameter of an array type must be definitely assigned by the caller. Therefore, there is no need to be definitely assigned by the callee. A ref parameter of an array type may be altered as a result of the call. For example, the array can be assigned the null value or can be initialized to a different array.
For example:
public static void MyMethod(ref int[] arr)
{
arr = new int[10]; // arr initialized to a different array
}