Feed Icon  

Contact

  • Bryant Likes
  • Send mail to the author(s) E-mail
  • twitter
  • View Bryant Likes's profile on LinkedIn
  • del.icio.us
Get Microsoft Silverlight
by clicking "Install Microsoft Silverlight" you accept the
Silverlight license agreement

Hosting By

Hot Topics

Tags

Open Source Projects

Archives

Ads

Previous Page Page 2 of 4 in the Silverlight category(RSS) Next Page

Twilight 1.5: Multiple Views with MVVM

Posted in Silverlight | UX | Twitter at Thursday, 26 February 2009 03:15 Pacific Standard Time

You may have noticed the new look for the Twilight Twitter Badge on my blog a few weeks ago. I wanted to add a few new looks for the badge and got one of them done but then decided I need to spend some more time on it before releasing it because I didn’t like the way the code was turning out. There were a couple of things I didn’t like:

  1. The code was too tightly coupled to the views/skins. This made it hard to add new views/skins without duplicating code.
  2. The views/skins weren’t blendable at all.

To start my rework I began with this post by the Expression Blend/Design team on simulating sample data in Blend. The post is a very simple yet workable solution for displaying design time data in Blend so that you can work on the layout of your application. The only change I made was how I detected design mode. After playing around with that sample I decided that to implement this in Twilight I would need to switch to a Model-View-ViewModel approach so I started doing some research into using this approach with Silverlight. In my research I came across this post by Ryan Keeter on using MVVM in Silverlight. It was a nice simple explanation that made sense to me so I set out to combine the expression team example and this MVVM example.

What I ended up with is pretty close to MVVM. I say pretty close because I don’t think it fully fits since the ViewModels hook into some of the Views Storyboard events and also control the Views VisualState transitions. Maybe that fits into MVVM, but it probably breaks some of the rules. However, for this tiny application it makes things a lot easier. I still have multiple Views per ViewModel and the Views have zero code which is what I really wanted.

There are two ViewModels that I’m using: ListViewModel and RotatingViewModel. Then on top of these two ViewModels are four Views: Default, Large, Small, and Tiny.

ListViewModel Views  

Default View

Large View

The ListViewModel is for views where there is just a list of tweets while the RotatingViewModel is for views that display a single tweet at a time.

RotatingViewModel Views  

Small

Tiny

 

 

 

 

You can switch between these views by setting the mode initParam equal to the view you want (example: mode=tiny). The Tiny view looks like the twitter counter badge but then pops the bubbles over the surrounding content. This is done using the windowless = true parameter and absolute positioning. Right now the Silverlight will float over the content below it even when the bubble isn’t showing, so you won’t be able to click through to that content. I might be able to figure out a better way to handle it, but for now that is a known limitation.

Since now all the view logic is in the ViewModel, writing tests is a lot easier. I’m still using the same Silverlight test framework, but thanks to this post by Justin Angel I added a few more complex tests using his WaitFor extension. The test coverage is still very light and I’m not testing the views at all, but I feel like I’m starting to get testing in Silverlight.

I’ve also added another option for hosting Twilight on your blog. You can now host it via Silverlight Streaming using an iframe. Add the following HTML to your page:

** Hosting it via Silverlight Streaming doesn’t support the Tiny mode since the Silverlight won’t be able to expand outside of the iframe.

In addition to hosting it via Silverlight Streaming, you can always self-host it or use the xap I have hosted on dreamhost at http://twilight.bryantlikes.com/twilight.xap. If you’re already using the hosted version, you can switch the mode by using the mode initParam as I mentioned above.

Hopefully this will serve as a great twitter badge for your blog and also a decent example of MVVM in Silverlight along with some unit testing examples as well. Feel free to join the project on Codeplex and create your own views. I am still working on at least one more version that will make the colors tweakable and maybe even detect what colors should be used based on the surrounding html.

Detecting Design Mode in Silverlight

Posted in Silverlight at Wednesday, 25 February 2009 01:46 Pacific Standard Time

One of the things I’ve been trying to getting a better understanding of is how to make the Silverlight projects I work on more blendable:

In general, WPF and Silverlight controls should be "blendable". ItemsControls need to display representative data within the design surface.

The problem, at least for me, is that every example out there to detect design mode uses:

var designMode = !HtmlPage.IsEnabled;

Since the Html Bridge is disable inside of Blend, this does work for the most part, but what about when your xap is hosted on another server? In this case the Html Bridge is disabled by default so if someone doesn’t configure it correctly they will get your design time data.

Mode HtmlPage.IsEnabled
Blend false
Visual Studio false
Local Xap true
Remote Xap false*
Streaming Silverlight true**

* This can be changed to true, but it is disabled by default.
** Enabled by default

So I was trying to come up with another method to detect design mode in Silverlight and here is the best I have come up with so far:

public bool IsDesignTime()
{
    try
    {
        var host = Application.Current.Host.Source;
        return false;
    }
    catch
    {
        return true;
    }
}

What happens is that Application.Current.Host.Source works great when the plugin is hosted in a web page and will return the path to the xap file, but in design mode trying to access that property throws an exception. So if you hit the exception then you’re in design mode, otherwise you’re in a web page. Not super elegant but it feels better to me than checking if the Html Bridge is enabled since that isn’t a true check.

Update: As Tom mentions in the comments, you can also use DesignerProperties.GetIsInDesignMode. But if your goal is to make your project more blendable then Visual Studio support might not be important.

Mode DesignerProperties.GetIsInDesignMode
Blend true
Visual Studio false
Local Xap false
Remote Xap false
Streaming Silverlight false

So with this check worst case you get no data in the Visual Studio designer, but the Visual Studio designer isn’t that great anyway. Blend is the real goal. So instead instead of the above code you can use this code instead:

public bool IsDesignTime()
{
    return DesignerProperties.GetIsInDesignMode(Application.Current.RootVisual);
}

Thanks for the tip Tom!

Twilight 1.1: Using a Yahoo Pipes Proxy

Posted in Silverlight | Twitter at Tuesday, 27 January 2009 06:54 Pacific Standard Time

I just pushed a minor update to Twilight that you can now download on the codeplex site (version 1.1). I really wanted to allow the xap file to be hosted on other servers since many bloggers don’t have the ability to host their own xap files. After reading Scott Barnes’ post about replacing his header with Silverlight I decided I would take a similar approach. Instead of using a callback or trying to get the data directly, Scott followed Jonas’ post on using Yahoo Pipes to proxy data to Silverlight. I took the same approach and during the process refactored some of the code by moving all the data logic out to a separate set of classes. Now when the xap loads it checks to see if it can access the Html Bridge and makes sure it is on the same domain. If it is then it will just use the standard Twitter callback method, otherwise it uses the yahoo pipes proxy I created.

pipes

The pipe I created simple takes a username and the number of tweets to return and grabs the twitter xml. I then use an HttpRequest in my code to get this xml from yahoo formatted as json which matches up to the json that I was getting from Twitter with the exception that there are a few wrapper objects I have to go through to get the tweets. I also moved all the update logic out of the page class and into the base data provider class since that made a lot more sense.

I think the new code makes it much cleaner and the end result is you can now just stick the object tag up on your blog and leave the xap hosted on my server if you’d like. Here is the html you can use for the hosted version:

<div id="silverlightControlHost">
  <object id="TwitterBadge" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="200" height="400">
    <param name="source" value="http://twilight.bryantlikes.com/Twilight.xap"/>
    <param name="minRuntimeVersion" value="2.0.31005.0" />  
    <param name="initParams" value="username=bryantlikes,count=10" />
    <div style='position:relative;'>
      <a style='z-index:0;' href='http://go.microsoft.com/fwlink/?LinkID=124807' style='text-decoration: none;'>
      <img src="http://twilight.bryantlikes.com/twilightNoSilverlight.png" alt="Get Microsoft Silverlight" style='border-style: none'/> </a>
     <div style='font-family:Arial;font-size:10px;position:absolute;top:230;left:10;width:175px;'>
      by clicking "Install Microsoft Silverlight" you accept the <br />
    <a href="http://www.microsoft.com/silverlight/resources/License.aspx?v=2.0">Silverlight license agreement</a>
  </div>
  </div>
  </object>
  <iframe style='visibility:hidden;height:0;width:0;border:0px'>
  </iframe>
</div>

Today I had my first sighting of Twilight in the wild over at Denny Boynton’s Blog.  Very cool!

Twilight Source Code Published

Posted in Silverlight | Twitter at Monday, 26 January 2009 10:21 Pacific Standard Time

This afternoon I put the Twilight source code up on CodePlex. Twilight is the Silverlight Twitter Badge that I created from my AgFeedReader Mix 10k contest entry. You can download the source and I also packaged up the Xap file along with support files if you don’t want to bother with the code.

I haven’t been able to get it to work when the xap isn’t hosted on the same server as the page itself, so for now there is no hosted scenario. Perhaps I’ll have to create some other proxy like Silvester uses. If you have any good ideas feel free to suggest them or better yet contribute to the project.

In my previous post on the subject I wrote that I was using the LinkLabel control to create the text with the linked embedded in it. There was also an external WrapPanel control that came with the LinkLabel source. However, in the end I switched to using a custom wrap panel that was based on the Silverlight Toolkit WrapPanel but was a much lighter version (I only need horizontal wrapping). I also found another issue with the LinkLabel control and after spending some time trying to fix it I decided that it also was overkill for what I needed. So while I used some of the same ideas I ended up writing some new code to handle this (I did credit both of these projects in both the source code and on the codeplex page).

TestsI also gave the Silverlight Unit Test Framework a try and the source code includes a test project. This was my first real experience with the framework and I definitely found it very useful. If you haven’t used it before I highly recommend Jeff Wilcox’s introduction post on the framework. It was very easy to use and I actually found a few bugs in my code through my tests (I didn’t do full TDD on this project but next time I think I will). When you run the test project it loads up right in the browser and runs the tests. I didn’t do very much UI testing, but I did test my wrap panel implementation by using the TestPanel that is part of the framework. That allowed me add TextBlocks and measure their size to determine how big my panel should be. Then I added an instance of my panel to the TestPanel to test it. This feature is very nice since measuring doesn’t work right unless the child is actually in the control tree, that that alone makes the test framework worthwhile. Even better was the fact that I didn’t have to modify a single line of code in my real project in order to allow the test framework to work. Well done!

exampleNoSl I also did some work to create a decent install experience after reading Tim Heuer’s several posts on the subject. If you don’t have Silverlight installed you will get an image that looks like the actual application but has a prompt to install Silverlight. I didn’t spend much time on this part, but it is a lot better than the big giant button you normally would get.

There is still lots of room for improvement and I would like to figure out the remote hosting option as well as create some cool animation for loading. But for now it is a very light weight (13k) Silverlight Twitter Badge.

Enjoy!

Twilight: A Silverlight Twitter Badge

Posted in ASP.Net/Web Services | Silverlight | Twitter at Friday, 23 January 2009 14:27 Pacific Standard Time

When Twitter first came out I signed up but never really caught on until recently. I finally figured out that you really need to follow some people first to get the hang of it. Now I enjoy using Twitter and read peoples tweets using Witty, a WPF Twitter client. Even though I only have a few followers, it still feels like you’re part of a bigger conversation since your own posts get mixed in with the posts of people you’re following.

So now that I’m using Twitter I wanted to put my latest tweets on my blog. Twitter provides a flash based Twitter badge and an HTML version as well, but since I’m a Silverlight developer I thought it would be cool to use Silverlight. I came across Silvester which is a Silverlight Twitter Widget and looks great, but I wanted to create a widget/badge that didn’t require a proxy server.

For my entry in the MIX 10K contest I created a Silverlight feed reader that would allow you to subscribe to a bunch of feeds and it would keep them updated and stored your subscriptions in isolated storage. Since you can’t actually access most feeds directly (unless the host has a client access file which most don’t) I used the Google Ajax Feed proxy to grab all my feeds. This worked great because Google has a client access policy that allows you to get the content plus it puts it all into a single format and returns it as json. All I had to do was generate classes in my application to mirror the object structure of the json and then use a DataContractJsonSerializer to deserialize the json into objects.

So when I started on my Twitter badge I basically took the AgFeedReader project and removed the isolated storage and the feed subscription interface. I really only needed a single feed which I would set using an InitParam. I was able to get my twitter feed using the Google Ajax Feed Proxy, but that proxy only returns the last four items from the feed and omits a lot of the rich data that Twitter provides. So I decided to try another approach.

I started by looking at the script that is part of the Twitter HTML badge. The key was the script they provide to get the feeds which includes a callback parameter. You call the json script and add a callback=YourJavascriptFunction. So in my Silverlight application I add two scripts to the page: the first is the Twitter Json script and the second is a stub javascript function that calls back into my Silverlight application. This gets around the security issue which prevents you from downloading the json directly.

Now back in my Silverlight application I get passed in a ScriptObject which is the json. This ScriptObject is really just an array of Tweets, but since it is an array I actually have to manually convert it to my .Net objects. There is a good MSDN page here that describes all the rules for the interop between javascript objects and .Net objects. Below is my method that gets called from Javascript:

[ScriptableMember]

public void TwitterCallback(ScriptObject json)

{

    twitList.ItemsSource = json.ConvertTo<Tweet[]>();

}

 

The twitList is my ListBox and the Tweet class is a .Net class that I created that mirrors the json returned by Twitter.

In order to display the Tweets I wanted to not just have text but have clickable links. The Silvester Twitter Gadget has a very nice LinkLabel control that will allow you to have a text area with clickable links. So instead of reinventing the wheel I just used that in place of my normal TextBlocks from the AgFeedReader project. I did change one line of code but for the most part it worked perfectly.

Anyhow, it is a pretty standard Twitter Badge right now, but that is only a few hours of work and I’m hoping to add a few more features to it. I’m hoping to put the xap along with some javascript helper files up on a server somewhere so that anyone can add it to their blog, but if you’re interested let me know and I’ll try to get it done this weekend. If you’re reading this through a feed reader, head over to my blog and you will be able to see the Twitter Badge in action.

Switching XAP Files on the Client Side

Posted in Silverlight at Monday, 22 December 2008 12:15 Pacific Standard Time

qingquan126778 asked the question in the Silverlight forums about how to switch between pages in Silverlight if the pages are in different xap files. First I pointed to Jesse Liberty’s post on multi-page applications (qinqquan wanted different xap files, not just pages) and then Mike Snow’s post on swapping between xap files using the ASP.NET server control (qingquan wanted client side only).

So since neither one was quite right, I coded up an example of my own that is based off Mike’s example but uses client side scripting instead of server side. Basically you grab a reference to the Silverlight plugin control via the onLoad event and then just set the Source property to the new xap.

function App2()
{
    slCtl.Source = "ClientBin/SilverlightApplication2.xap";
}

Download Source Here

BTW – Did you vote on my 10k Content Entry yet? :)

MIX 10k Challenge Entry

Posted in Silverlight at Monday, 22 December 2008 07:35 Pacific Standard Time

So my entry in the Mix 10K challenge is up in the gallery. It was a fun little project to create and I went well over 10k many times during the project and then had to whittle it back down each time. It is a feed reader that allows you to subscribe to feeds and it stores your subscriptions in Isolated Storage. I thought it was somewhat original, but then I watched this video on the contest and Adam even mentions an RSS reader, so I guess it was little obvious. :)

If you’re looking to enter the contest a few good posts on the subject are Adam’s post and Bill Reiss’ post.

Anyhow, check out my feed reader and be sure to vote!

Silverlight Dependency Properties

Posted in Silverlight at Monday, 15 December 2008 02:08 Pacific Standard Time

I’ve seen this question a number of times in the Silverlight Forums, so instead of just answering it one more time I decided to answer it here so I can refer back to this. The question generally looks like this:

I have create a dependency property and the setter isn’t getting called during data binding. My dependency property is declared as follows:

public class MyClass : Control

{

 

 

    public int MyProperty

    {

        get { return (int)GetValue(MyPropertyProperty); }

        set

        {

            SetValue(MyPropertyProperty, value);

            // some custom code here

        }

    }

 

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...

    public static readonly DependencyProperty MyPropertyProperty =

        DependencyProperty.Register("MyProperty", typeof(int), typeof(MyClass), new PropertyMetadata(0));

 

 

}

 

The reason why the setter isn’t called here (at least the way I understand this), is that when data binding sets this value it isn’t calling the public property. Instead it is using the SetValue on the dependency object instead. So the custom code is never called. What you need to do is add a PropertyChangedCallback to the DependencyProperty registration as follows:

public int MyProperty

{

    get { return (int)GetValue(MyPropertyProperty); }

    set

    {

        SetValue(MyPropertyProperty, value);

    }

}

 

// Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...

public static readonly DependencyProperty MyPropertyProperty =

    DependencyProperty.Register("MyProperty", typeof(int), typeof(MyClass), new PropertyMetadata(0, MyPropertyChanged));

 

private static void MyPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)

{

    ((MyClass)o).OnMyPropertyChanged((int)e.NewValue);

}

 

private void OnMyPropertyChanged(int newValue)

{

    // custom code goes here instead

}

 

 

Now whenever the property changes the OnMyPropertyChanged method will get called. Notice that this is where you put your custom code to handle the property changing. This code will get called when the public property setter is called or when the property is changed using the SetValue method.

More information on Dependency Properties can be found here.

Deep Zoom Image Generation with DeepZoomTools.DLL

Posted in Silverlight | Deep Zoom at Wednesday, 26 November 2008 22:49 Pacific Standard Time

Yesterday I saw that the Expression Blend and Design team had blogged about the new DeepZoomTool.dll:

In our most recent release of Deep Zoom Composer, one of the major changes we made was to change how we generated the image tiles both for designing as well as exporting your Deep Zoom Content. In the past, ever since our first release at MIX, our image encoding was done using a combination of SparseImageTool.exe and ImageTool.exe command line tools. Starting with this release, we have retired those tools and have shifted to a preview version of a .NET based DLL that provides image generation capabilities.

Building Deep Zoom Images via code is something that I’ve wanted to do for some time. I’ve tried to figure out how to do this many different ways, but I’ve never gotten it to work. So I was pretty excited to try out this new API for Deep Zoom. I still don’t fully understand it all, but I was able to create a very simple program to generate a deep zoom image based on a bunch of photos.

First, I read all the image files into a List of strings. I created my code so that it will go into subfolders as well:

private static List<string> GetImagesInDirectory(string path)

{

    return GetImagesInDirectory(new DirectoryInfo(path));

}

 

private static List<string> GetImagesInDirectory(DirectoryInfo di)

{

    List<string> images = new List<string>();

 

    // get all the images in this directory first

    foreach (var fi in di.GetFiles("*.jpg"))

    {

        images.Add(fi.FullName);

    }

 

    // get all the directories with their images

    foreach (var sub in di.GetDirectories())

    {

        images.AddRange(GetImagesInDirectory(sub));

    }

 

    return images;

}

 

Next, once you have the list of Images, you need to generate all the Deep Zoom images which are folders containing tiles of the image at different zoom levels. We generate these images using the ImageCreator. For a great overview on Deep Zoom and Tiles, check out Jaime Rodriguez: A deepzoom primer.

List<string> images = GetImagesInDirectory(source);

List<string> data = new List<string>();

 

foreach (var image in images)

{

    ImageCreator ic = new ImageCreator();

 

    ic.TileSize = 256;

    ic.TileFormat = ImageFormat.Jpg;

    ic.ImageQuality = 0.95;

    ic.TileOverlap = 0;

 

    string target = dest + "\\output_images\\" + Path.GetFileNameWithoutExtension(image);

 

    ic.Create(image, target);

    data.Add(Path.ChangeExtension(target, ".xml"));

}

Now we should have a bunch of folders and xml files in our “output_images” folder in our destination. Now that we’ve created all the images and their tiles we need to create the collection using the CollectionCreator. The collection creator takes in the list of xml files that we generated and creates another xml file plus some more image tiles.

CollectionCreator cc = new CollectionCreator();

 

cc.TileSize = 256;

cc.TileFormat = ImageFormat.Jpg;

cc.MaxLevel = 8;

cc.ImageQuality = 0.95;

 

cc.Create(data, dest + "\\output");

 

Now we can actually start to use our Deep Zoom image. However, we will need a Silverlight Deep Zoom project in order to display the images. To do this just create a Deep Zoom project, add an image or two, and then export it to a Silverlight Project. In that project delete the contents of the GeneratedImages folder inside of the client bin and then set the dest variable in the above code to the path of the GeneratedImages folder you just cleaned out. Point the source variable to a folder containing the folder you want to load the images from and run it. You should get an output.xml file in the GeneratedImages folder.

You will need to make a couple of changes to the Silverlight project once you’ve done all that. First, we need to position our images since right now they are just a collection. We do this by setting the ViewportWidth and ViewportOrigin. I’m still trying to fully understand these, but the best explanation I’ve seen so far is also on Jaime Rodriguez’s blog: Working with Collections in Deep Zoom.

void msi_ImageOpenSucceeded(object sender, RoutedEventArgs e)

{

    //If collection, this gets you a list of all of the MultiScaleSubImages

    //

    var x = 0.0;

    var y = 0.0;

    foreach (MultiScaleSubImage subImage in msi.SubImages)

    {

        subImage.ViewportWidth = 5.333;

        subImage.ViewportOrigin = new Point(-x, -y);

        x += 1;

 

        if (x >= 5)

        {

            y += 1.333;

            x = 0.0;

        }

    }

 

    msi.ViewportWidth = 1;

}

Now we’ve arranged out images on the viewport, but we also need to point the MultiScaleImage to our output.xml instead of what it was before (do that in the page.xaml file). Once we’ve done that we should be able to run and see our generated deep zoom!

deepzoom

There is still a lot of work to do on this, like figuring out the proper ViewPortWidth based on the number of images and image size, but this is a good starting point. I’m hoping to get some more time to play with this this weekend and I’ll post more as I figure it out.

Happy Thanksgiving!

Update: Just uploaded my project which should make it a lot easier to try out. Just set the source and dest variables, run the console app, and then build and run the website. Have fun!

Silverlight IValueConverter vs. TypeConverter

Posted in Silverlight at Sunday, 23 November 2008 22:40 Pacific Standard Time

This is something that wasn’t clear to me so I decided to blog about so that I could fully understand it. Both IValueConverters and TypeConverters are used to do conversions (imagine that!), but they are used differently.

TypeConverters are used by the Xaml parser during parse time to convert values in the Xaml into values in CLR objects. So when you set Height=”100”, height isn’t a string so it has to be converted to a double. This is done using a type converter. Type converters are also one-way since once the value has been converted from Xaml to CLR it doesn’t have to go back. Custom type converters must be placed on the class they will be used on in order for them to work since otherwise the Xaml parser doesn’t know how to convert the value. There is a good MSDN article on TypeConverters which offers much more information.

IValueConverters are used during data binding via a property path. Typically these get created as a static resource in your Xaml file and then are referenced in the binding. Unlike type converters, value converters can go both ways since bindings can be two way bindings. Since value converters are specified in the binding they are much more dynamic and don’t require any references such as the type converters do. Value converters are also more flexible in that they can be passed a parameter via the ConverterParameter. You can read this great blog post on how this works if you’re interested.

A good example of how value converters make Silverlight more extensible is this question in the Silverlight forums. Odegaard was binding to a Dictionary object and was trying to get one of the keys to show up in his TextBlock.Text property. However, even though WPF supports this property bag type of binding, there is no way to do this directly in Silverlight. To get this type of binding to work you can use an IValueConverter. In this case the value converter would get the key in the dictionary and return the proper value. You can see the code for this in the original post (although the questioner didn’t like my implementation because it was too complicated, I thought it was rather simple).

I tried to come up with a more generic approach instead of requiring the dictionary to be of type Dictionary<string,string>, however the best I was able to do was have the value type be assignable but the key still had to be a string.

public class DictionaryItemConverter : IValueConverter

{

    public string ValueType { get; set; }

 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)

    {

        Type generic = typeof(Dictionary<,>);

        Type[] typeArgs = new Type[] { typeof(string), Type.GetType(ValueType) };

        Type dictType = generic.MakeGenericType(typeArgs);

 

        if (dictType.IsInstanceOfType(value))

        {

            return dictType.GetMethod("get_Item").Invoke(value, new object[] { parameter });

        }

        throw new InvalidCastException(string.Format("Dictionary is not of type Dictionary<stirng,{0}>.", ValueType));

    }

 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

    {

        throw new NotImplementedException();

    }

}

So hopefully this post has been helpful for you in understanding IValueConverters vs. TypeConverters and when to use them. It has cleared it up for me. :)

Technorati Tags:
Previous Page Page 2 of 4 in the Silverlight category(RSS) Next Page