Showing posts with label c#. Show all posts
Showing posts with label c#. 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 :)


.

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 :)
.

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

.

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


.

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

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


.

Monday, June 9, 2008

[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

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.

Tuesday, March 4, 2008

[Silverlight] Cloning an XAML element

BLAH!!! As of the time of writing this post, there is no way to 'Clone' a XAML element in Silverlight... at least none that I can find with my poor google skills.

MY APPROACH

Ideally what I'd like to do is be able to take an element and iterate through all of it's properties and make an exact copy of each property - thus creating an exact clone [except for the name, which I'd have to change].

I currently have a recursive function that will check what type of element the object is and the redirect to the corresponding 'clone' function, which makes exact copies of specific properties for that object. This is done recursively on all of the children of that element [if children exist].

public UIElement CloneUIElement(UIElement copyMe, string instance, Canvas parent)
{
return RecurseCloneUIElement(copyMe, instance, parent);
}

public UIElement RecurseCloneUIElement(UIElement copyMe, string instance, Canvas parent)
{
UIElement temp = copyMe as UIElement;
switch (copyMe.ToString())
{
case "System.Windows.Controls.Canvas":
temp = CloneCanvas((Canvas)copyMe, instance, parent);
break;
case "System.Windows.Shapes.Rectangle":
temp = CloneRectangle((Rectangle)copyMe, instance, parent);
break;
... [All I have is canvas and rect]
}
return temp;
}

public Canvas CloneCanvas(Canvas copyMe, string instance, Canvas parent)
{
Canvas clonedCanvas = new Canvas();
clonedCanvas.SetValue(Canvas.NameProperty, copyMe.GetValue(Canvas.NameProperty) + "_" + instance);
clonedCanvas.SetValue(Canvas.LeftProperty, (double)copyMe.GetValue(Canvas.LeftProperty));
clonedCanvas.SetValue(Canvas.TopProperty, (double)copyMe.GetValue(Canvas.TopProperty));
clonedCanvas.SetValue(Canvas.WidthProperty, (double)copyMe.GetValue(Canvas.WidthProperty));
clonedCanvas.SetValue(Canvas.HeightProperty, (double)copyMe.GetValue(Canvas.HeightProperty));

// ONLY CLONING SOLID BRUSHES AT THE MOMENT.
SolidColorBrush cloneColor = copyMe.GetValue(Canvas.BackgroundProperty) as SolidColorBrush;
if (cloneColor != null) { clonedCanvas.SetValue(Canvas.BackgroundProperty, cloneColor.Color.ToString()); }

foreach (Visual child in copyMe.Children)
{
clonedCanvas.Children.Add(RecurseCloneUIElement((UIElement)child, instance, clonedCanvas));
}
return clonedCanvas;
}

FREEZABLE OBJECTS

It appears that in the 3.0 framework there are 'freezable' objects, which include brushes. Apparently there is a clone functionality with those objects, however I'm guessing it's not included in the silverlight framework since I cannot access the functionality they are talking about.


Reference Links:
How to copy Shape object through C#?
Freezable .Clone Method