Showing posts with label silverlight. Show all posts
Showing posts with label silverlight. Show all posts

Monday, January 26, 2009

[Silverlight 2, C#] Data Binding and Event Handlers

So, right to the point, it seems that you cannot data bind event handlers.

What I wanted to do was be able to bind a name and delegate function to a custom menu item.
[ListBox x:Name="ItemList" Width="Auto" Height="Auto"]
[ListBox.ItemTemplate]
[DataTemplate]
[StackPanel Orientation="Horizontal"]
[TextBlock Text="{Binding itemname}"
FontFamily="Arial" Font Foreground="Black"
MouseLeftButtonDown="{Binding itemaction}"/]
[/StackPanel]
[/DataTemplate]
[/ListBox.ItemTemplate]
[/ListBox]

But I was getting a compiler error:
Error 5 The "ValidateXaml" task failed unexpectedly.
System.InvalidOperationException: Stack empty.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Stack`1.Pop()...

After a quick trip to the Silverlight forums I found out that you cannot databind to an event handler - which made some sense after I found this on the MSDN page for DataBinding:

The binding engine gets information from the Binding object about the following:



My Solution: Sneak the function delegate into the tag property
Since I couldn't bind the event directly I decided to sneak the delegate into the tag property of the textbox, and then setup a generic mouseLeftButtonDown handler that would read out the tag and cast it to my delegate, and then invoke it. So far it seems to work pretty well.

[ListBox x:Name="ItemList" Width="Auto" Height="Auto"]
[ListBox.ItemTemplate]
[DataTemplate]
[StackPanel Orientation="Horizontal"]
[TextBlock Text="{Binding itemname}"
FontFamily="Arial" Font Foreground="Black"
Tag="{Binding itemaction}"
MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" /]
[/StackPanel]
[/DataTemplate]
[/ListBox.ItemTemplate]
[/ListBox]

and then in the code behind:

private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Get the tag info and run it.
MenuActionDelegate func = ((FrameworkElement) sender).Tag as MenuActionDelegate;
func.Invoke();
}

If anyone else has a more elegant solution, please let me know!!!

.

Tuesday, January 20, 2009

[Silverlight 2, C#] Fun with Namespaces

Hi everybody!

Alright - so if you've read my other posts, you'll know that I'm working on a WYSIWYG-type graphics editor - and I've been dealing with naming issues with regards to having to name and clone thousands of elements on a canvas. Also in my application, when I drag and stretch, I create a ghost of the base element. This also required cloning, and up until now, namespace checks.

I was aware that a user control actually creates it's own namespace, such that you can have the same x:name is multiple controls. This is obviously a very, very handy thing to have. I wanted to be able to separate some content from the rest of my application easily, so that I could reduce the number of name checks I need to do as a result of cloning elements based on hardcoded strings.

Try 1: Creating an essentially empty UserControl
Originally, I had tried to create a helper UserControl called "SafeNamespace" which was essentially an empty control with a Canvas root.

[UserControl x:Class="Graphics.SafeNamespace"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"]
[Canvas x:Name="LayoutRoot"]

[/Canvas]
[/UserControl]


This was mildly annoying because I could not easily treat this like a canvas [to my knowledge] and I wrote small helper functions in the xaml.cs to allow for simplier setting and getting of the LayoutRoot content. It was just a little ugly - it worked, it was just icky.


Better Method: Extending the Canvas Class
After a little searching I came across this forum post which talked about extending the Canvas class itself, instead of extending the UserControl class. This also allows you to implement custom functionality onto the Canvas if you desired, but for me I was really only looking for the ability to create a seperate namespace.

xaml:
[Canvas x:Class="Graphics.SafeNamespaceCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"]
[/Canvas]


and

xaml.cs
public partial class SafeNamespaceCanvas : Canvas
{ ... }



In short, creating an extention of a class was a nice way for me to achieve some namespace independance... and was extremely handy given the large number of named elements I was dealing with! Just thought I'd pass along the idea :)


.

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/



.

Monday, December 8, 2008

[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, 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.



.

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

.

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.


.

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!


.

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#] 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

[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