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.


.

No comments: