Click here to Skip to main content
Email Password   helpLost your password?

Foreword

This article presents a debugger visualizer for WPF called Woodstock. After Woodstock was released to the world, it was used as a prototype to design and develop a superior visualizer called Mole v4 For Visual Studio - With Editing. We recommend that you use Mole v4 For Visual Studio - With Editing as your primary WPF and Visual Studio visualizer, because its functionality is a superset of what Woodstock has to offer. However, if you are interested in learning about the evolution of Mole by seeing what came before it, be sure to read this article.

Table of Contents

Introduction

This article presents a Visual Studio debugger visualizer called "Woodstock" which enables you to view the visual tree. It provides detailed information about all properties on every element in the visual tree, and a snapshot image of each element, allowing you to more easily debug complex WPF user interfaces.

Background

Every WPF developer knows and loves Snoop, the powerful free utility created by Pete Blois. Amongst other things, Snoop allows you to view the visual tree of any WPF application, and inspect the properties of any element. This is a huge time-saver, and a great way to learn about WPF.

Despite the tremendous powers of Snoop, it does not really mesh well with debugging WPF code in Visual Studio. Snoop is a separate application which attaches itself to a WPF application's process. You cannot step through WPF code and use Snoop on that UI at the same time. I, Josh, often found myself debugging some WPF code and wishing that Snoop somehow worked in Visual Studio. That's why Woodstock was born.

I created a small subset of Snoop's functionality, and implemented it as a debugger visualizer. Since the uber-visual tree inspection application is called "Snoop", I decided to name my little visualizer "Woodstock". In case you are not familiar with Peanuts, here's the lowdown on Woodstock.

Josh's Contribution

Throughout the article, when you see the word "I", it is referring to me, Josh Smith. I created Woodstock and wrote this article about it. The burden of updating the code, and this article, falls squarely on my shoulders. Woodstock is my invention, but it would not be nearly as useful and efficient without the numerous suggestions and bug reports I received from dozens of people across the globe!

Karl's Contribution

Karl Shifflett has been a huge help in making Woodstock a great debugging tool. Ever since I published the initial article, he has made many great suggestions, sent me code snippets, reported bugs, etc. To thank him and show my appreciation, I decided to add him as an author of this article.

Florian's Contribution

Shortly after this article was published, Florian Kruesch published an article about a visualizer which shows you an image of the element you're inspecting in the debugger. We agreed to merge his visualizer and article into Woodstock. Karl and I changed his code a bit so that it would work well in Woodstock, but the initial idea of an image visualization came from Florian.

Installing Woodstock

If you just want to download the visualizer and install it, follow these steps:

  1. At the top of this article, click the "Download the visualizer" link.
  2. Save the ZIP file to disk and extract it.
  3. Place "JoshSmith.WpfVisualizer.Woodstock.dll" at one of these locations:
    1. VS install path\Common7\Packages\Debugger\Visualizers
    2. My Documents\Visual Studio 2005\Visualizers

Instead, if you click the "Download the code and demo" link, you will get the Woodstock.zip file, in which there are two Visual Studio solutions. The one called "WpfVisualizer" contains the Woodstock visualizer code. The other, "WpfVisualizerTestApp", is a demo app which allows you to try out Woodstock. Be sure to drop the visualizer DLL into your Visualizers directory first before running the test app.

If you have any trouble installing the visualizer, there is a bleak amount of documentation on how to do so here.

Visual Studio Version Information

If you are using this visualizer in Visual Studio 2005, then be sure to download the DLL which was compiled for VS2005. It turns out that the Microsoft.VisualStudio.DebuggerVisualizers.DLL assembly has a different version for VS2008, so I made a separate build of Woodstock for VS2008 users. The source code and demo app are compiled against VS2005 with the Orcas extensions, so that people who have not yet switched to VS2008 can use it too.

However, if you decide to build Woodstock in VS2008, be sure to remove the reference to Microsoft.VisualStudio.DebuggerVisualizers.DLL and add a reference to version 9.0.0.0 of that assembly. If you do not, you will get a nasty exception when trying to use Woodstock.

Making Woodstock Work with XBAPs

One big advantage Woodstock has over Snoop is that you can use it to debug XBAP applications. Here is what you need to do to enable that:

  1. Right-click on the XBAP project in Solution Explorer and open the Properties page.
  2. Under the Security tab, select the "This is a full trust application" radiobutton.
  3. Be sure to set it back later on to partial trust in order to properly test deployment.

Thanks to CodeProject member "ivolved" for that tip!

How to Use Woodstock

You can use Woodstock just like any other debugger visualizer. Here's what the datatip looks like when you mouse over a DependencyObject-derived object after hitting a breakpoint:

When you open the Woodstock visualizer, it looks like this:

The TreeView on the left represents the entire visual tree of the UI you are debugging. Initially, the element which you hovered the mouse over in the code editor will be selected in the TreeView, but you are free to select any element in the visual tree. If an element has its Name property set, then that name will appear next to the element's type. Each element that has descendants has the number of descendants displayed beside it in parentheses.

The DataGridView on the right shows all of the properties of the selected element. If a property is a dependency property, then the "Value Source" column shows what is providing the effective value of that property (i.e., is it a locally provided value? a value provided by a template? a Style? a system theme? etc). Having the source of a dependency property's value can make it much easier to track down issues where one property might be set from any number of external influences (which is the heart and soul of DPs).

Clicking on a button to the left of a property name will copy a Google search query to your clipboard, so that you can paste that URL into a Web browser's address box and research the property. I wanted to just open a Web browser to that URL, but attempting to do so always made Visual Studio crash when running on Windows XP (but, oddly enough, not Vista).

You can filter the properties shown in the grid by typing a case insensitive filter string into the TextBox toward the bottom of the Form. If you do not want to view the attached properties, simply uncheck the CheckBox next to the TextBox. If you only want to view attached properties, leave the CheckBox checked and type "." as your filter text string. ;)

When you click on the "Selected Element Snapshot" tab, you will see an image of the element currently selected in the TreeView. Here's a screenshot of that:

UIElements and FrameworkElements must be initialized and loaded before they can be displayed. As a result, when you put a breakpoint in, for example, a Window's constructor, you won't see anything if you check out the visuals in that Window.

In case you have never used a debugger visualizer before and want some more information, read this page in the docs.

Limitation

There is one issue which might possibly make using Woodstock difficult. Visual Studio's "Debugger Visualizer" feature only allows a visualizer to have a brief amount of time to serialize its data. If your visual tree is huge, or your machine is bogged down processing other things, etc., then Woodstock might take too long and it will time out. Visual Studio will show an error dialog stating: "Function evaluation timed out."

I did my best to work around this limitation by optimizing the way that information about the visual tree is retrieved and represented. Before making the optimizations, I tested Woodstock against an application with a gigantic visual tree and long-running background processes, and it timed out frequently. After making the optimizations, it never timed out. Hopefully, those optimizations will prevent you from seeing that annoying error message, too.

How it Works

Debugger visualizers are strange little creatures. You have to keep in mind that there are two logical parts involved: debugger-side code and debuggee-side code. Visual Studio's debugger allows you to inject some code into itself and the process being debugged. The code in the debugger process shows the visualizer UI. The code in the process being debugged allows you to package up the data that you want to display in the visualizer. Once that data has been serialized, it gets shipped over to your visualizer in the debugger process, at which point you can turn it back into live objects and display them. For more information about the architecture of visualizers, read this article in the SDK.

Basic Architecture

A visualizer must specify a class for which it provides visualizations, including subclasses of that class. We want our visualizer to work for any DependencyObject, or subclass thereof. The problem is that DependencyObject is not serializable, so we cannot rely on the standard serialization behavior of the debugger visualizer framework to make life nice and easy for us. Instead, I created a class which intercepts requests to serialize the visual tree, and then created a parallel hierarchy of serializable objects which contain the visual tree information we want to display in the visualizer. Here is that class:

/// <summary>
/// Serializes the element tree into DTOs.
/// </summary>

public class ElementTreeVisualizerObjectSource : VisualizerObjectSource
{
    public override void GetData(object target, Stream outgoingData)
    {
        DependencyObject depObj = target as DependencyObject;

        // This is the magic line of code which creates a serializable
        // representation of the entire visual tree of which the target
        // element is a member. The element property information and
        // snapshots are not created at this time. 
        WpfElementTree elementTree = new WpfElementTree(depObj);
        _binaryFormatter().Serialize(outgoingData, elementTree);
    }
    // Other methods omitted for now...
}

The visualizer itself is a simple class which only shows a custom WinForms Form, as seen below:

/// <summary>
/// A debugger visualizer for WPF elements.
/// </summary>

public class ElementTreeVisualizer : DialogDebuggerVisualizer
{
    protected override void Show(IDialogVisualizerService windowService, 
    IVisualizerObjectProvider objectProvider)
    {
        using (Form displayForm = new ElementTreeVisualizerForm(objectProvider))
        windowService.ShowDialog(displayForm);
    }
}

In the AssemblyInfo.cs file, an attribute is applied which Visual Studio uses to figure out what type(s) this visualizer is used for, as well as some other information. That attribute is seen below:

[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(WpfVisualizer.ElementTreeVisualizer),
typeof(WpfVisualizer.ElementTreeVisualizerObjectSource),
Target = typeof(System.Windows.DependencyObject),
Description = "Visual Tree Visualizer (Woodstock)")]

Getting Information About All of the Properties

One piece of the code which took me (Josh) a while to get right was the logic which stores information about all of an element's properties. Information about a property is stored in an instance of my WpfElementProperty struct. A WpfElement object has a WpfElementPropertyList which stores information about every property of that element. The logic which populates that list is seen below:

private void Initialize(DependencyObject propertySource)
{
    PropertyDescriptorCollection props = 
            TypeDescriptor.GetProperties(propertySource);

    foreach (PropertyDescriptor prop in props)
    {
        PropertyDescriptor resolvedProp = prop;
        string baseValueSource = null;

        DependencyPropertyDescriptor depProp = 
        DependencyPropertyDescriptor.FromProperty(prop);

        if (depProp != null)
        {
            baseValueSource = DependencyPropertyHelper.GetValueSource(
            propertySource, depProp.DependencyProperty).BaseValueSource.ToString();
            resolvedProp = depProp;
        }

        string name = resolvedProp.Name;
        object value = resolvedProp.GetValue(propertySource);
        base.Add(new WpfElementProperty(name, value, baseValueSource));
    }
}

Lazily Loading Element Information

A far more challenging thing to implement was the logic which lazily loads the property information and snapshot image of each element in the visual tree. Initially, I serialized all of that information for every element in the tree in the ElementTreeVisualizerObjectSource's GetData method, seen above. It turns out that Visual Studio has a timeout monitor for that method (deadlock detection?), which caused the method to be terminated before it was able to complete serializing the data for large visual trees. When the timeout occurs, the Woodstock UI does not appear, and the visualizer is unusable.

I worked around this problem by redesigning the way that the property information and the snapshot image are created for each WpfElement instance. Instead of creating them all in one fell swoop, I create them on an as-needed basis. This prevents all of that data from being serialized at once, which makes the GetData method lightning fast (so it won't timeout).

When the WpfElementTree is created in the ElementTreeVisualizerObjectSource.GetData method, the WpfElement instances do not have any of that extra information. When the user selects an element in Woodstock's TreeView, it checks to see if the newly selected WpfElement is already populated with the property information and snapshot data. If not, we send that element over to the debuggee-side code and expect it to be returned with the missing data. That code is in the ElementTreeVisualizerForm class, as seen below:

void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
    WpfElement element = (WpfElement)e.Node.Tag;

    if (!element.IsPopulated)
    {
        WpfElement populatedElement = this.CreatePopulatedElement(element);
        e.Node.Tag = populatedElement;

        if (e.Node.Parent != null)
        {
            // Give the parent element a reference to the new child.
            WpfElement parentElement = (WpfElement)e.Node.Parent.Tag;
            parentElement.ReplaceChild(element, populatedElement);
        }

        element = populatedElement; 
    }
    
    this.RefreshGrid(element);
    this.RefreshImage(element);
}

The method which actually requests that the ElementTreeVisualizerObjectSource populates the WpfElement is seen here:

WpfElement CreatePopulatedElement(WpfElement element)
{
    // Since serializing and deserializing all of this element's 
    // children might take a very long time, remove them for now
    // and we'll add them back in later.
    List<WpfElement> children = new List<WpfElement>(element.Children);
    element.Children.Clear();

    // Ask the ElementTreeVisualizerObjectSource, 
    // which is running in the debuggee process,
    // to fill up this element's property info 
    // and take a snapshot of it.
    MemoryStream inputStream = new MemoryStream();
    _binaryFormatter.Serialize(inputStream, element);
    Stream outputStream = _objectProvider.TransferData(inputStream);
    inputStream.Close();

    // Get the populated WpfElement back from the debuggee process.
    WpfElement populatedElement = 
        (WpfElement)_binaryFormatter.Deserialize(outputStream);

    // Add the element's children back to its list.
    populatedElement.Children.AddRange(children);

    // Keep a reference to the snapshot image so 
    // that we can easily dispose of it later.
    _elementSnapshots.Add(populatedElement.Snapshot);

    return populatedElement;
}

When the object provider's TransferData method is invoked, it results in the ElementTreeVisualizerObjectSource's TransferData method to be called back in the debuggee process. That logic is seen below:

/// <summary>
/// The visualizer calls this method when an element's property information
/// and snapshot is needed to be displayed in the UI.
/// </summary>

public override void TransferData(
    object target, Stream incomingData, Stream outgoingData)
{
    WpfElement element =(WpfElement)_binaryFormatter.Deserialize(incomingData);
    Debug.Assert(!element.IsPopulated, "Element should not be populated.");
    WpfElement populatedElement = this.CreatePopulatedElement(element);
    _binaryFormatter.Serialize(outgoingData, populatedElement);
}

The method which populates the WpfElement with property information and a snapshot is seen here:

WpfElement CreatePopulatedElement(WpfElement element)
{
    DependencyObject depObj = _elementTree.GetDependencyObjectByID(element.ID);
    WpfElementPropertyList properties = new WpfElementPropertyList(depObj);
    Bitmap snapshot = VisualSnapshot.TakeSnapshot(depObj);
    element.Populate(properties, snapshot);
    return element;
}

One crucial thing to notice here is that we have an association between the real WPF element and a WpfElement instance which represents it. That link is formed by a simple integer ID value. WpfElement has an ID property, and the real WPF element is put into a Dictionary<int, DependencyObject>, where the integer key is the ID value.

The two ID values are set up in the WpfElement constructor:

private WpfElement(
 DependencyObject currentElem, 
 DependencyObject initialElem, 
 Dictionary<int, DependencyObject> elementMap)
{
    // Create an association between this object and the real WPF object
    // that it represents by giving them both the same ID.
    _id = WpfElement.elementCount++;
    elementMap.Add(_id, currentElem);
    // Other code elided...
}

When the debugger process sends over a WpfElement to be populated, the element's ID is used to look up the real WPF object in the dictionary.

Taking Snapshots

The image processing code can be found in the VisualSnapshot class. Its primary method looks like this:

public static Bitmap TakeSnapshot(object target)
{
    Bitmap bitmap = null;
    if (target is BitmapSource)
    {
        bitmap = BitmapSourceToGdiImage(target as BitmapSource);
    }
    else if (target is FrameworkElement)
    {
        FrameworkElement fe = target as FrameworkElement;
        if (0 < fe.ActualWidth && 0 < fe.ActualHeight)
        {
            BitmapSource bitmapSource = CaptureVisual(fe);
            bitmap = BitmapSourceToGdiImage(bitmapSource);
        }
    }

    if (bitmap == null)
    {
        // Return a new Bitmap so that the cached instance 
        // does not get disposed of somewhere else.
        return new Bitmap(VisualSnapshot.UnavailableSnapshot);
    }
    else
    {
        // Return a new Bitmap because we can get a 
        // "corrupt memory" exception otherwise.
        using (bitmap)
            return new Bitmap(bitmap);
    }
}

Revision History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralIt's working.!:-).
Epsilone3
23:35 20 Nov '07  
It's working great


GeneralDoes it work with the release version of VS2008? [modified]
atanamar
4:37 20 Nov '07  
I'm trying this out with the release version of VS2008, and when I try to open the visualizer I get the error:

"Unable to cast object of type 'WpfVisualizer.ElementTreeVisualizerObjectSource' to type 'Microsoft.VisualStudio.DebuggerVisualizers.VisualizerObjectSource'."

Maybe I'm doing something wrong?
Thanks.

modified on Thursday, May 22, 2008 10:33 AM

GeneralRe: Does it work with the release version of VS2008?
Josh Smith
4:42 20 Nov '07  
I haven't installed the release version yet, but I think I know what's wrong.  You should download the source code, remove the WpfVisualizer project's reference to Microsoft.VisualStudio.DebuggerVisualizers.dll, then add it back in (make sure it points to the latest version, which is 9).  Rebuild, redeploy, and all should be well.


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralRe: Does it work with the release version of VS2008?
atanamar
4:48 20 Nov '07  
Thanks, I'll give that a try.
Sorry to bug you so fast about the release version! Wink
GeneralRe: Does it work with the release version of VS2008?
Josh Smith
4:50 20 Nov '07  
No problem, I expected it would happen! Smile
Please drop a comment to let me know if that did or did not work for you.  Thanks.


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralRe: Does it work with the release version of VS2008?
atanamar
4:56 20 Nov '07  
Yup, that did the trick. Thanks so much. It's a fantastic tool!
GeneralRe: Does it work with the release version of VS2008?
Josh Smith
4:57 20 Nov '07  
Great!  Thanks for the feedback.


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralCool
Rama Krishna Vavilala
2:03 18 Nov '07  
I always wondered what TransferData was forSmile


Co-Author ASP.NET AJAX in Action

CP Quote of the Day:
It is the same Friday that blooms as a new enriching day with novelty and innovation for us every week. - Vasudevan Deepak Kumar

GeneralRe: Cool
Josh Smith
3:41 18 Nov '07  
Me too!  It was quite a relief when I finally figured that one out, because it allowed me to fix the big problem with Woodstock: timing out. Big Grin


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralThanks :)
Florian Kruesch
5:19 16 Nov '07  
Thanks for integrating my little contribution. It would be very cool to send an image for each element, but I think you mentioned a timeout going on in the remoting connection between Visualizer and ObjectProvider that prevents this...

cheers
Florian

--
[Planet XAML.net]

GeneralRe: Thanks :)
Josh Smith
5:27 16 Nov '07  
No problem, Florian.  Thanks for letting me add your code into Woodstock!

Yes, the debugger-side code must be very efficient because it is racing against the clock.  I'd love to provide an image for each element, but it just takes too long.  Perhaps there is a way to skin this cat, but I'm not aware of it yet...


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralGreat stuff!
R.Eberle
4:39 16 Nov '07  
This is really great stuff. I can't wait to see where this leads to. It just keeps getting better every day.

Is there any way to be able to see an image of any item in the visual tree? This would be really cool. I realize you can't load each individual image at startup, but even if we had to click a button to retrieve the image, it would still be awesome.

I also ran into an issue with a big initial image. I had to maximize Woodstock to see the area I wanted. Maybe you could put a scrollviewer around the initial image.



Rick Eberle
GeneralRe: Great stuff!
Josh Smith
4:57 16 Nov '07  
Thanks Rick! 
R.Eberle wrote:

Is there any way to be able to see an image of any item in the visual tree?


I really wish we could load an image of any element in the visual tree, but I am not sure how it could be implemented.  You see, all of the data about the visual tree (the elements, properties, and that one image) are created in the debugger's process.  That data is then serialized and sent over to the process in which the visualizer lives.  At that point the visualizer deserializes the data and displays it, but has no access to the visual tree itself.  I've looked into it, but it appears that Visual Studio's visualizer support does not allow you to request additional information from the debugger-side code.  If I find a way to do it, I certainly will give it a shot.

R.Eberle wrote:
Maybe you could put a scrollviewer around the initial image.

I was thinking about that too! Smile Keep in mind, though, that the visualizer UI is WinForms...not WPF.  So there is no ScrollViewer.  I think that I might be able to use a WinForms Panel, though.  It's been a while since I did WinForms programming, so it's all coming back to me on an as-needed basis. Wink


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralRe: Great stuff!
Josh Smith
17:02 17 Nov '07  
Rick,

I just updated the article.  I found a way to load images of every element in the tree, and added Scrollbars for the snapshot image. Smile


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralRe: Great stuff!
R.Eberle
3:45 19 Nov '07  
Thats great, this has really become a very useful tool and it just keep getting better. Keep up the good work. These debugger visualizers are really helpful, I hope to see a lot more of them posted.
GeneralThank you...
Marc Clifton
13:42 14 Nov '07  
... for getting rid of that wierd .FindAll.ForEach notation, which seemed rather inefficient! The code looks much improved. Now I'll give you my 5! Wink

Marc




GeneralRe: Thank you...
Josh Smith
14:20 14 Nov '07  
Marc Clifton wrote:
.. for getting rid of that wierd .FindAll.ForEach notation, which seemed rather inefficient!

;P  Bah, you philistine! 

Thanks for the vote, Marc.


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralRe: Thank you...
Sacha Barber
1:12 15 Nov '07  
Marc

Im glad you mentioned that syntax, I didnt like that either.

For something truly crazy try this

UIUtility.SetSelectedItem(treeView1,
new SetSelectedInfo()
{
Items = Enumerable.Range(7, 4)
.Select(i => new ExampleTreeItem(i)),
CompareMethod = (x, y) => x.Data == y.Data,
OnSelected = (container, options) =>
{
var treeItem = (TreeViewItem)container;
var dataItem = (ExampleTreeItem)treeItem.DataContext;

treeItem.IsSelected = true;
treeItem.BringIntoView();

// Display the item's full path
textBoxPath.Text = dataItem.GetPath();
},
OnNeedMoreItems = (container, options) =>
{
((TreeViewItem)container).IsExpanded = true;
}
}
);


I found this at the following article http://www.codeproject.com/WPF/TreeView_SelectionWPF.asp and its based on using some of the new C# 3.0 features like object initialisers (which is what the above is), lambdas, LINQ etc etc.

I think there is a real danger that people will just go mad and create totally unreadable blocks of code.



Sacha Barber
A Modern Geek - I cook, I clean, I drink, I Program. Modern or what?

My Blog : sachabarber.net

GeneralRe: Thank you...
Marc Clifton
1:46 15 Nov '07  
Sacha Barber wrote:
I think there is a real danger that people will just go mad and create totally unreadable blocks of code.


Which is exactly what I've been saying in the lounge! Thanks for that great example!

Marc


JokeRe: Thank you...
Josh Smith
1:53 15 Nov '07  
Gee whiz, I sure am glad my article inspired a thread about bad programming style. Sigh


:josh:
My WPF Blog[^]
Without a strive for perfection I would be terribly bored.

GeneralRe: Thank you...
Marc Clifton
2:03 15 Nov '07  
Josh Smith wrote:
Gee whiz, I sure am glad my article inspired a thread about bad programming style.


I was going to put an apology about polluting your article with a very off topic thread, but I got distracted (by what, I no longer remember) and hit the post button before remembering. Smile

Marc


GeneralRe: Thank you...
Sacha Barber
10:23 15 Nov '07  
er, yeah sorru Josh.

This is by no means a slur on your code, cos its great, I only didnt like the part that Marc asked about, but you changed that (apparently, havent checked).

I just think the example I showed to Marc is way to intensive to work out.

Sacha Barber
A Modern Geek - I cook, I clean, I drink, I Program. Modern or what?

My Blog : sachabarber.net

GeneralRe: Thank you...
Sacha Barber
10:22 15 Nov '07  
most welcome sir

Sacha Barber
A Modern Geek - I cook, I clean, I drink, I Program. Modern or what?

My Blog : sachabarber.net

GeneralRe: Thank you...
ivolved
5:34 15 Nov '07  
Sacha Barber wrote:
I found this at the following article http://www.codeproject.com/WPF/TreeView_SelectionWPF.asp and its based on using some of the new C# 3.0 features like object initialisers (which is what the above is), lambdas, LINQ etc etc.


I'm not seeing any object initializer being used here. It is using LINQ and Lambdas however. Honestly I think anonymous methods (which Josh was using) and Lambdas are more readable than creating functions that serve no other purpose than to be event callbacks if for nothing more than allowing me to see what's happening in the call back without jumping to another section of the code.
GeneralRe: Thank you...
Sacha Barber
10:21 15 Nov '07  
Have another look, each of the values within the {} for the SelectedInfo are indeed setting properties. I think this code is not nice.

But of course you are entitled to your opinion

Sacha Barber
A Modern Geek - I cook, I clean, I drink, I Program. Modern or what?

My Blog : sachabarber.net


Last Updated 31 Dec 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010