A WPF Project Needs Structure

October 1st, 2007

Dear Dr. WPF,

I am about to begin a rather large WPF project.  I’ve worked on plenty of development efforts involving Windows Forms projects and even a few Win32 projects, but this will be my first foray into WPF.  Can you give me general guidance on how to best structure a Visual Studio solution that is targeting WPF?

Sincerely,
Sacha V. 


Hi Sacha,

When people are first getting started with WPF, they often feel more than just a little intimidated.  The platform is so big and something as basic as project structure may seem overwhelming.  If you find yourself in this position, my advice is to charge ahead blindly!  Don’t let the unknowns prevent you from making immediate progress. 

I’m happy to share some things I’ve learned on this subject…

Just to be clear, I’m not referring to application architecture in this post.  (However, I’m more than willing to expound on that topic too.  But if you’re just starting, you would probably find such a discussion mind numbing at this point.  If you really care, let’s just say that I tend to follow an architecture similar to the model-view-viewmodel approach described by John Gossman.  I never had a name for it until he blogged about it, and I still don’t have a name for it.  I think his chosen term suffers from the same branding problems as the WPF platform itself, so I refuse to call it m-v-vm. ) 

In this discussion, I’m talking only about how you structure and manage the projects, files, resources, etc, within your Visual Studio/Expression Blend solution.  I believe this is what you are asking about, correct?

The good news is that it’s fairly simple to change your structure along the way as long as you regularly revisit the topic and keep things heading in the right general direction.

Is there a right way to structure a WPF solution?

Yes, absolutely.

What is the right way to structure a WPF solution?

There is not one.

Huh?

Okay, before you accuse me of contradicting myself, let me just clarify that this is an exercise in semantics and these two questions are actually quite different.  (If everyone could please pull out their high school grammar books, we’ll continue…)  In the first question, the indefinite articlea” is used (“a right way”) so the question is asking if there is at least one right way.  In the second question, the definite articlethe” is used (“the right way”) to effectively ask for the one and only right way.

My whole point here is that you shouldn’t get caught up thinking there is only one correct way to structure your solution.  There is definitely not a one-size-fits-all structure for WPF solutions.  The general rule is that the project, itself, should determine the project structure.  WPF is no different than any of the previous platforms you’ve targeted in this respect.

Having said that, I definitely think there are some patterns that can be followed to make WPF solutions more manageable, sensible, and approachable for the developers and designers working on the project. 

Use Project Folders

This one goes without saying… but I’m saying it anyway.  Good project structure begins by organizing project files in a meaningful way.  Unless we’re talking about an extremely simple project with one or two windows or navigation pages, you should be leveraging folders within your project to keep files logically organized.  My projects typically have at least a rudimentary set of root folders, as shown in the Solution Explorer image to the right.

Organize by Resource Type

WPF applications tend to have many different types of resources.  For large applications, it makes sense to use separate subfolders for common types of resources.  In most of my projects, you will at least find a root project folder named Resources.  Within there, you are likely to find additional folders with names like Images, Media, Styles, Converters, CultureStrings, etc.  Some of these folders (Images, Media) are likely to contain embedded binary files, whereas others (Styles, Converters, CultureStrings) are likely to contain resource dictionaries for application resources.  The markup for the application class will typically contain references that merge in the appropriate application-wide resources.

<Application x:Class="StructureMatters.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:StructureMatters"
    Startup="ApplicationStartup">
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/presentationframework.aero;component/themes/aero.normalcolor.xaml" />
        <ResourceDictionary Source="/StructureMatters;component/Resources/Converters/ValueConverters.xaml"/>
        <ResourceDictionary Source="/StructureMatters;component/Resources/Icons/CommonGlyphs.xaml"/>
        <ResourceDictionary Source="/StructureMatters;component/Resources/Icons/CustomCursors.xaml"/>
        <ResourceDictionary Source="/StructureMatters;component/Resources/Styles/NativeControlStyles.xaml"/>
        <ResourceDictionary Source="/StructureMatters;component/Resources/Styles/EditModeControlStyles.xaml"/>
      </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

The code-behind for the application class may selectively merge in additional resource dictionaries.  For example, if the application needs to support dynamic locale switching, the appropriate UI culture resources will be merged into the application resources at startup.  A different dictionary of localized resources may later be swapped in if the user changes locale.

Organize Projects by Usage Scenarios

If a class is going to provide functionality that will be needed in other projects outside of your current application, go ahead and create a separate project for it within your solution and build it into a separate assembly.  Use project references to ensure that the correct dependencies are created between the different projects in your solution.  In this area, Visual Studio makes it very easy to develop solutions that share code across multiple assemblies.

Leverage the Object-Oriented Nature of the Platform

Hey, did you know that WPF is built on an object-oriented framework called .NET?  I’m sure you did Sacha.  I’m being a bit facetious here because a good deal of code I’ve seen recently leads me to believe that this concept is foreign to a lot of people.  (I plan to do a separate blog on some of my pet peeves in this particular area.  For some reason, perfectly good OO developers seem to toss out a lot of their OO skills when they begin writing WPF code.)

The reason I bring this object-oriented notion up here in a discussion on project structure is because the arrangement of class files within a solution should typically be related to the actual class hierarchies contained therein. 

If I’m looking at a class that provides data access functionality, it should be located alongside the other classes that provide similar functionality.  Furthermore, if they can leverage shared base functionality, data access classes should derive from a common base class.  The base class files should be located in a logical location in relationship to their derived classes (such as alongside them or maybe in a primitives directory, assuming the base classes are not expected to be instantiated directly).

Use Meaningful File Names and Namespaces

My recommendation is that a single code file should never contain more than one class (unless we’re talking about a nested class).  Furthermore, the filename of that code file should exactly match the name of its contained class. 

If code files are arranged within project folders, the folder hierarchy should match the namespace hierarchy for the contained classes.  For example, a C# class named BetterVisualTreeHelper within the DrWPF.Windows.Media namespace should be found within a file named BetterVisualTreeHelper.cs located within the folder path DrWPF\Windows\Media.

Visual Studio will do its best to assist you in this effort by creating default namespaces for new code files that match your project’s folder structure.

Keep Your XAML Files Editable in Blend

If you have skilled designers working on the project, they will probably be far more productive when they can edit the UI files directly in Blend.  In version 1.0 of Blend, there are still a few things that will cause a XAML file to fail to load within the Blend design surface.  These are usually small things that can be avoided or worked around.  Make sure that your designers are regularly opening the XAML files in Blend because it is much easier to isolate what caused a failure if you discover the failure soon after the offending change.  I’d love to provide an exhaustive list of the things to avoid, but such a list would very quickly become outdated, so I’ll just recommend going to the Blend/WPF forums when you have questions about markup that won’t open in Blend.

The same guidance can also be offered for the VS 2008 designer (a.k.a., Cider).  Unlike Blend, this product is still in Beta so expect to find more problematic areas at this stage.

The good news is that with each new pre-release of Blend 2.0 and Cider, there are fewer and fewer compatibility issues.  Soon, this whole topic will hopefully become a non-issue.

Revalidate Structure Regularly

Every project evolves.  I said it up front and I’ll say it again now.  You should revisit your project structure on a regular basis.  If you do this, you can make changes along the way to accommodate the changing nature of the project.

Now Get Started

Your project cannot even begin to take its proper structure until you begin to structure your project.  So go ahead and get started… just plan to make changes in structure whenever they become necessary.

I’m sure I’ve left out some obvious things here, so I welcome others out there to chime in with your recommendations on project structure.

Cheers!
Dr. WPF

Can I bind my ItemsControl to a dictionary?

September 16th, 2007

I’ve seen a number of forum posts lately expressing a desire for an observable dictionary.  Here are links to a couple of them:

Thread 1: Observable Dictionary, problem with Remove

Thread 2: Bind observable dictionary

As promised in my response to the latter thread, I am now providing a sample demonstrating how one might implement an observable dictionary.  You can download the sample here.

The Observable Dictionary Sample

In this sample, I demonstrate how to bind to a dictionary of button styles.  The styles are sorted based on their Key values in the observable dictionary.  (Clearly, this should be treated as a nonsensical illustration for demonstration purposes only.)

On the left side of the window is a ListView that is bound to the observable dictionary.  If you click an odd-indexed button in the ListView, its corresponding entry is removed from the dictionary.  If you click an even-indexed button, its entry is duplicated in the dictionary.

On the right side of the window is a ComboBox whose items are bound to the same dictionary.  Beneath the ComboBox is a Button whose style is bound to the selected value of the ComboBox.  If you click this button, the dictionary will be cleared and reloaded.

As you click around, you will notice that the bound controls respond appropriately to any changes in the observable dictionary.

So why would someone want to do this?

Dictionaries are easy to work with in code.  Perhaps you’ve already written an application that leverages a dictionary to store and retrieve in-memory data.  You may now want to provide a view of the dictionary entries in your user interface. 

Unfortunately, to provide a dynamic view of your dictionary data, you would need to do a lot of extra work.  Namely, you would need to write code to synchronize some observable collection with your dictionary whenever you modify it. 

Wouldn’t it be nice if the dictionary, itself, were observable?

The Observable Dictionary Class

What we clearly need is an “observable” dictionary class.  You will find an example of such a class in the ObservableDictionary.cs file in the provided sample.  What does it mean for a dictionary to be observable?  In WPF, an observable class is simply a collection class that provides change notifications whenever its collection changes.  It does this by implementing the INotifyPropertyChanged and INotifyCollectionChanged interfaces.  This allows it to serve as the “ItemsSource” of a collection control (like a ListBox, ComboBox, or any other ItemsControl).  These controls know how to monitor the collection for changes.

For a detailed explanation of how binding to a collection works, see the MSDN documentation.  Here is a good starting point.

So how do you implement an observable dictionary?

Dictionaries basically work by aggregating an internal collection of key-value pairs.  People often start by trying to derive a class from Dictionary<TKey, TValue> or by trying to implement IDictionary<TKey, TValue> in a class that aggregates a dictionary.  The idea is that they could then add the requisite INotifyPropertyChanged and INotifyCollectionChanged interfaces and have an observable dictionary.

There’s a major problem with this approach.  Observable collections are indexed by integer.  In order to fire the necessary collection change notifications, you must know the index of an entry when it changes.  Unfortunately, none of the interfaces exposed by the Dictionary<TKey, TValue> class are indexed by integer.  And if you derive directly from Dictionary<TKey, TValue>, you do not have access to the underlying collection.  As a result, an attempt to create an observable dictionary by deriving from or aggregating a dictionary won’t work.

To truly create an observable dictionary, you need to aggregate your own collection (usually of type KeyedCollection<TKey, TValue>).  Then you must implement a whole slew of interfaces on top of the collection, as shown in the following class declaration:

    public class ObservableDictionary <TKey, TValue> :
        IDictionary<TKey, TValue>,
        ICollection<KeyValuePair<TKey, TValue>>,
        IEnumerable<KeyValuePair<TKey, TValue>>,
        IDictionary,
        ICollection,
        IEnumerable,
        ISerializable,
        IDeserializationCallback,
        INotifyCollectionChanged,
        INotifyPropertyChanged

By implementing all of the above interfaces, you ensure that your dictionary class can be used interchangeably with the CLR’s Dictionary class.  You should only need to change the declaration from Dictionary<TKey, TValue> to ObservableDictionary<TKey, TValue> in your code.

Pros and Cons

The benefit to using an observable dictionary, of course, is that the dictionary can serve as the ItemsSource for a databound control and you can still access the dictionary in code the same way you access any other dictionary.  It is truly an indexed dictionary of objects.

There are certainly some limitations inherent in the very idea of making a dictionary observable.  Dictionaries are built for speed.  When you impose the behaviors of an observable collection on a dictionary so that the framework can bind to it, you add overhead.

Also, a dictionary exposes its Values and Keys collections through separate properties of the same name.  These collections are of types Dictionary<TKey, TValue>.ValueCollection and Dictionary<TKey, TValue>.KeyCollection, respectively.  These CLR-defined collections are not observable.  As such, you cannot bind to the Values collection or to the Keys collection directly and expect to receive dynamic collection change notifications.  You must instead bind directly to the observable dictionary.

The Observable Sorted Dictionary Class

Another thing to note is that a dictionary doesn’t typically store its data in a deterministic order.  When binding to an observable dictionary, you cannot simply apply a sort order via a CollectionView because the exposed interfaces do not support sorting.  For this reason, I include an ObservableSortedDictionary class in the attached sample.

Binding to an Observable Dictionary

When you bind to an observable dictionary, you are really binding to a collection of KeyValuePair objects. A KeyValuePair is an object which makes the entry’s key available via an appropriately named Key property and its value available via a Value property.  Your item templates must take this into consideration and provide the appropriate binding paths.  The provided sample illustrates how to do this.

All the Standard Caveats Apply

As always, this sample is provided “as is”.  It has not been heavily tested and there are probably lots of improvements that could be made.  Use it and modify it as you see fit.  Let me know how it works for you, what improvements you make, what bugs you find, etc.

Cheers,
Dr. WPF

The Doctor is on a quest for 5… Yes 5 Gold Stars

September 11th, 2007

In an earlier post, I mentioned that I’ve been hanging out in the MSDN WPF Forum lately.  

I was feeling pretty good about my 100th post the other day, and in fact, I was even considering retirement from the forums so I could spend my afternoons playing golf.  (Isn’t that what doctor’s do when they retire?)

Then I noticed something disturbing!  Right there under my name were two little gold (well, yellow really) stars.  For some reason, I had never even noticed the rating system before.  And now, on the crest of my retirement, I discover that I’ve only scored 2 out of a possible 5 stars… clearly there is still much work to be done.

How much?  Well, I did a quick search and found this information on the MSDN recognition system. 

Begin Edit:

Strike that!

Okay, I feel pretty good about earning 2000 points in my first 2 weeks, but come on!  Do I seriously have to earn a million points to retire with 5 stars?  Am I the only one that thinks the cost of that last star is just a little too high?  I figure I can reach 4 stars (15000 points) in about 3 months at my current pace.  But then that last star is going to cost me roughly 19 more years!!  I don’t think so!

Okay, clearly my understanding of how the point system works was drastically off! 🙂

The values in that chart are the upper limit for the star level, not the requirement.  So in order to get my 5 gold stars, I only need to achieve 15000 points.  Much Better! 

Of course, that also means I don’t yet have the 2000 points that I thought I had.  🙁

I discovered that by clicking my name, I can see exactly how many points I have.  Currently, I have 851 recognition points, so I still have a ways to go!  But at least its within reach!  Yep… still a “noob” at this forum thing!  🙂

End Edit

Image Manipulation using WPF Imaging Classes

September 8th, 2007

The following question recently appeared in the WPF forum:


Is there posibility of resizing BitmapImage using WPF?

I do not want to resize an Image control. I want to resize image itself so when i convert it to bytes and stores it in database it has desired size.


In my response to that question, I included some sample code demonstrating how you might resize an image by leveraging the BitmapImage class to decode the image to the desired pixel width and height and then save the converted image back to a disk file or store it in a database.

I also mentioned that there are some additional imaging classes that can be leveraged for other common image manipulation tasks.  After receiving a couple of inquiries about these other classes, I decided to expand my sample a little. 

Here is a sample application that demonstrates how to use the CroppedImage and TransformedImage classes.  It also includes the resize code from the earlier sample.

Note that I’ve written this sample as a simple .NET console application.  (This should reinforce the idea that WPF is more than just a “presentation” framework.)  You can pass the app commands like rotate left, rotate right, flip horizontally, flip vertically, and crop square. 

Hope others find this useful.

Cheers,
Dr. WPF

Supplying an Object Reference in the ConstructorParameters Collection of an ObjectDataProvider

September 2nd, 2007

Dear Dr. WPF,

I have a .NET 2.0 data collection object that aggregates RSS feeds and maintains the incoming posts in an in-memory collection (as well as saving them to a data store). The class has no associated UI… it just provides the data as well as a few events that can be used to filter (accept/reject) posts as they arrive.  I have used it quite successfully in several different applications.

I recently decided to enhance the class to better support .NET 3.0 scenarios.  As such, the posts are now maintained in an observable collection, which works great for databinding.  But I would also like to support the routed event model and rather than requiring consumers of my object to attach event handlers, like in the 2.0 version, I’d like to have the object raise bubbled events.

This is where the trouble comes…  As mentioned earlier, the control has no knowledge of the UI.  It just knows about the data.  In order to raise routed events, it needs a target element.  To support this, I’ve created a constructor that accepts a UIElement, and if present, I will raise events on that element.  This works fine when I create my data object in code, but I would like to support creating it in XAML using an ObjectDataProvider.

Here is what I would like to do:

<Grid Name="RssGrid">
  <Grid.Resources>
    <ObjectDataProvider x:Key="RssData" 
        ObjectType="{x:Type rss:RssFeeder}">
      <ObjectDataProvider.ConstructorParameters>
        <Binding ElementName="RssGrid" />
      </ObjectDataProvider.ConstructorParameters>
    </ObjectDataProvider>
  </Grid.Resources>
  <ListBox DataSource="{StaticResource RssData}"
      ItemsSource="{Binding Path=RecentPosts}" ... />
</Grid>

But this doesn’t work because bindings can only target dependency properties.  The ConstructorParameters collection is a CLR property.

Is there any way to do this in XAML?

Sincerely,
Marie
 


Hi Marie,

It’s funny how the same question will pop up all at once from several different sources.  Yours is one such example.  I have received variations of this same question from no less than 4 different people within the last month.  It typically takes one of the following forms:

In markup, how do I pass an instance of an object …

1.  in the ConstructorParameters of an ObjectDataProvider?

2.  as the ConverterParameter of a Binding?

3.  as the value of a CLR property (that is not backed by a dependency property)?

And just last week, I saw this version of the same question (very similar to your scenario) in the WPF forum on the MSDN site.  In my response to that post, I said I would blog about an approach that I sometimes use to do this.  I think this solution will work nicely for you also.  You’ll find the promised details below.

Best regards,
Dr. WPF

 

Introducing the ObjectReference Markup Extension

First, let me say that although this solution can be used as an answer to all 3 of the scenarios described above, it’s not always the most appropriate solution.  In this earlier post, I provided a MultiBinding approach that I believe is often a more dynamic answer for question 2.  And question 3 can sometimes be better accommodated by using a one-way-to-source (or two-way) binding on another property wherein the source (the CLR property) essentially becomes the target.  I will likely blog about that approach in a future post.

Enough blather.

So how do you pass an object instance to the ConstructorParameters collection of the ObjectDataProvider?  The short answer is…

It Can’t Be Done

… using the native XAML support in 3.0 or 3.5.  More specifically, unless the object is a resource, there is no way to directly reference it in markup.  If the target property is a dependency property on a dependency object within the visual tree, then a binding can be used to create an indirect reference to the object.  But in all of the cases above, the target is not a dependency property, so this won’t work.

One strength of WPF is that it’s more than just a framework… it’s an extensible “platform”.  So what can we do?  We can extend markup!

A New Markup Extension

To solve the problem at hand, I introduce to you a markup extension I’ve created called ObjectReference.  You can use this extension in your projects by adding this small code file to the project. 

You are certainly already familiar with a number of native WPF markup extensions:  {Binding}, {TemplateBinding}, {StaticResource}, {DynamicResource}, {x:Null}, {x:Static}, {x:Type}, {x:Array}, etc.  Just like all of these classes, the ObjectReference class derives from the MarkupExtension base class and provides extended functionality for XAML-based scenarios. 

Usage in Markup

The ObjectReference extension can be used in markup in two ways:  first as a “declaration” on an object and second as a “reference” to an earlier declaration.  Both of these uses can be seen in the following example:

<Grid xmlns:dw="clr-namespace:DrWPF.Markup"
    dw:ObjectReference.Declaration="{dw:ObjectReference RssGrid}" >
  <Grid.Resources>
    <ObjectDataProvider x:Key="RssData" 
        ObjectType="{x:Type rss:RssFeeder}">
      <ObjectDataProvider.ConstructorParameters>
        <dw:ObjectReference Key="RssGrid" />
      </ObjectDataProvider.ConstructorParameters>
    </ObjectDataProvider>
  </Grid.Resources>
  <ListBox DataSource="{StaticResource RssData}"
      ItemsSource="{Binding Path=RecentPosts}" ... />
</Grid>

Note the use of an attached Declaration property to declare the object reference.  This is one method of declaring a reference on a dependency object.  In this case, a reference is created for the Grid object and it is assigned a Key value using the string “RssGrid”.

Later, the object is referenced in the ConstructorParameters collection by using a second ObjectReference with the same Key value.

If the target object is not a dependency object, you can declare a reference by setting an existing property using the ObjectReference extension.  In this case, you must set the IsDeclaration property to true when creating the ObjectReference, as shown here:

<winforms:MonthCalendar 
    Name="{dw:ObjectReference mc, IsDeclaration=True}" >

Because IsDeclaration is true, the reference is treated as a declaration for the MonthCalendar object.  In this case, the supplied key value of “mc” is passed straight through to the Name property.  It is essentially the same as saying Name=mc, except that it also creates a reference to the object.

Download a Sample

If you’ve examined the code in the sample I posted earlier in my forum response, note that it is slightly different that the version described herein.  I have updated the extension to make it fit for wide consumption and more applicable to other scenarios, such as referencing non-dependency objects.  You can download the updated ObjectReference sample here.

How it works

Let’s take a look at how this ObjectReference markup extension works…

Like any markup extension, our class derives from MarkupExtension and overrides the ProvideValue() method to return a resolved value.  The IServiceProvider parameter supplied to this method provides access to the parser’s context and allows us to know things such as which property the extension is targeting and the exact instance of the object that owns the property.  This is very helpful for our purposes.

If you look at the code in the ProvideValue() function, you’ll see that it first checks to see if we’re creating a declaration or a reference.  If it’s a declaration, then a reference to the target object is added to a static dictionary of weak references using the Key property as the dictionary key for the reference.  In this case, the Key value is returned as the result of the ProvideValue() function.  If the ObjectReference is being used as a reference (rather than a declaration), the ProvideValue() function looks up the supplied Key in the dictionary and returns the object stored earlier.

Sidenote:  Since we are maintaining references in a static dictionary, it is important that we only keep weak references to the objects.  Otherwise, our references would keep the objects alive indefinitely.  We certainly don’t want to leak objects.

Limitations

There are definitely some limitations to be aware of with this approach. 

Parse order matters

First and foremost, this solution is very dependent on the order in which the markup is parsed.  The declaration must be parsed before the reference.  Keep in mind that XAML is parsed from top to bottom.  This is similar to the way static resource references work, but not exactly.  Static resources are resolved based on the tree of elements, whereas, with our extension, it is purely based on parse order.  The reference can appear in another tree entirely and, as long as that tree is parsed first, the reference will resolve.

It’s not a binding

Second, note that the reference is not a binding.  It is resolved exactly once at parse time and it resolves based on the values in the static dictionary at that point in time.  If you change a reference later, it will have no effect on the earlier returned object.

References will be overwritten

Also, note that a reference will be overwritten if another declaration is parsed having the same Key value.  Most of the time, this will be the desired behavior.  For example, if you parse a XAML page that contains a declaration on its root element and references in the same page, you’ll want the references to refer to the declaration for that instance of the page.  There is no way to get at the earlier references after they’ve been replaced.

The ObjectReference class must be in the project

You must include the ObjectReference.cs file in the project.  If you use ObjectReference extensions in loose XAML files, other parsers may not be able to parse the files.  To work around this limitation, you could compile a separate assembly including the extension and include it alongside the loose XAML.  The xmlns namespace mapping in the XAML files would need to reference the assembly containing the ObjectReference class.

The reference dictionary is never compacted

To clean up this extension, I really should periodically walk the dictionary of weak references and remove entries for objects that no longer exist.  So far, I’ve just been too lazy to do that.  You’ll note that I’m providing the ObjectReference.cs file under a BSD open source license, so feel free to make any such improvements that you see fit.  J

Let me know how it works for you!

Please let me know in what creative ways you are able to use this markup extension.

Cheers,
Dr. WPF

Support Your Local Pub

August 29th, 2007

Recently, one of my peers informed me that due to my lack of participation in the WPF community, I’m just not a good citizen.  I told him to go to h… well…  you get the gist.

I was feeling a twinge of guilt about this, so I decided to look up my most recent posts in the WPF… er… uh… “Avalon” community forums.  (Well that can’t be good.)  Upon seeing the timestamps on those posts, I was feeling a slightly larger twinge of guilt.  Then I looked at the actual content…  WOW! 

How did we survive in a world without Grid?  Was there really once a native element called FlowPanel?  And the binding syntax… that’s just wrong!  Okay, clearly it’s been too long and I might just be a bad citizen.

Sidenote:  I was tempted to include some links to those posts, but they are all under the name I was using prior to joining the witness protection plan.  So in the interest of protecting my family, who desperately would like to distance themselves from my geekiness, I’m leaving those links out.

To ease my conscience, I’ve been hanging out in the WPF MSDN Forum for the last few days.  I’ve got to admit… this is a pretty cool place!  I plan to pop in here more frequently.  It’s amazing how much the community has grown and what a wealth of knowledge is available now.  And the volume of activity completely blew me away.  If you haven’t been there lately, stop being a bad citizen and check it out!

Hosting Office in a WPF Application

August 24th, 2007

note 

Updated on December 17, 2009

The approach described in this article for hosting office documents in WPF is no longer supported.  Microsoft has recently pulled the DSO Framer control from its knowledge base.  🙁

Please contact Microsoft Developer Support directly if you have questions regarding this decision.

 If a new supported solution for hosting Microsoft Office applications within WPF becomes available, I will try to post a sample.

Cheers,
Dr. WPF


Dear Dr. WPF,

Is it possible to host Microsoft Excel inside of a WPF application? Do you have any sample code?

Sincerely,
Rob
 


Hi Rob,

It’s certainly possible to host a Microsoft Office application inside of a WPF application. And just to prove it, I’m writing this entire post inside of Microsoft Word while it’s being hosted inside my WPF application.

WPF Hosting WordFeel free to download the code for this sample. This sample will work for hosting Word, Excel, PowerPoint, or Visio documents. It should host Project documents also, but I don’t have Project, so I couldn’t verify this. And I should note that hosting Visio 2007 documents proved to be very flaky. The Visio host crashed more often than not. The other hosts seemed pretty stable.

You will need to install the DSO Framer control prior to running the sample. More on that below…

So yes, it’s possible to host an Office application, but that doesn’t necessarily mean it’s easy! There are definitely a lot of caveats, disclaimers, qualifiers, stipulations, and limitations (yep, even the thesaurus works in the hosted scenario!) when hosting any Win32-based window (a.k.a., an HWND) within a WPF app. Most of these are documented in the SDK in topics like WPF Interoperation: ”Airspace” and Window Regions Overview and Hosting a Microsoft Win32 Window in WPF. In the latter article, special attention should be given to the sections entitled “Notable differences in output behavior” and “Notable differences in input behavior”.

Hosted Office applications come with a whole set of their own challenges (keeping the document focused, keeping application menus in sync with document menus, etc). If you go down the path of hosting an Office app, you should expect some technical challenges and a potential steep learning curve, especially if you’re considering office automation.

There are code samples in the SDK that demonstrate how to host an ActiveX control inside your WPF application. So if you can find a simple ActiveX wrapper for your Office application, then you’re all set, right?

Well, unfortunately it’s not that easy when it comes to hosting Office. An Office application, like Excel, has much larger requirements for its host container. The host must be an Active Document Container. This container implements a number of COM interfaces above and beyond those found in a simple ActiveX host.

There are a couple of Active Document Containers readily available on most Windows machines: 

1. Internet Explorer

2. the Windows Forms WebBrowser control

The simplest approach to hosting an Office application inside a managed application involves hosting the Windows Forms WebBrowser control and pointing it at an Office document. If all you care about is simple hosting, this approach might work for you.

SIDEBAR: For the record, I should point out that there is also an unmanaged WebBrowser control (shdocvw.dll) that ships as part of Internet Explorer. This control can be hosted in an unmanaged app (or even in a managed app using the instructions in this article, but why would you do that when there’s already a managed control?). Indeed, the Windows Forms WebBrowser control is just a managed wrapper around the Internet Explorer WebBrowser control. As such, Internet Explorer must be installed for any solution that involves either WebBrowser control.

Usually, however, if you are hosting something like Excel, you need to automate the document (to load, save, or print it, invoke automation commands, etc). The WebBrowser control does not give you much access to the document-related automation classes. (For information on the Office automation classes, check out the vast Office Development documentation in the SDK.) For this level of control, you need a better Active Document Container. Unfortunately, Microsoft has not released any such “supported” container. It would be great if they could put out a managed control that could serve as an Active Document Container. But so far, the only thing they offer is an “unsupported” container in the form of an ActiveX control called DSO Framer control.

The DSO Framer control was produced a few years back by the good folks in Microsoft Developer Support. Although their name says it (“Support”, that is), they don’t do it (“Support”, that is) for this control. The DSO Framer control (along with its source code… yes, you get the full source) is provided “as is”. Microsoft doesn’t support it and Dr. WPF doesn’t support it either… However, we both use it!

My sample of WPF hosting Word (illustrated above and available for download) is indeed built using the DSO Framer control. It is an extremely simple implementation of a WPF application hosting an ActiveX control. In this case, that ActiveX control just happens to be an Active Document Container.

NOTE: I could not get the most recent version of the DSO Framer control (compiled as a 32-bit control) to run on my 64-bit Vista box. It runs well on my 32-bit Vista installation. On my x64 machine, the application complains that the control is not registered, even though I can verify and instantiate an instance just fine in OleView. Not sure if this is a problem with the control or a configuration problem on my machine. If others encounter the same problem, I’d love to hear about it. Maybe someone in Microsoft Developer Support could try to reproduce this failure and look into a fix (hint, hint)… Oh yeah… it’s not a supported control. Maybe if I say “pretty please”.

FIX: Several people have advised that compiling the WPF application to specifically target the x86 platform (rather than “Any CPU”) fixes the above load issue on x64.  Thanks to all for this fix!  😀

Anyway, I hope you find this information and sample helpful!

Best regards,
Dr. WPF

Can my value converter access the target of the binding?

August 18th, 2007

Dear Dr. WPF,

In my application, I’m using a value converter to convert a GUID to a static resource.  The GUID is accessible in my DataTemplate through a binding like this:

<DataTemplate>
  <Grid Height="Auto" Width="Auto">
    <TextBlock Text="{Binding Path=ID}" />
  </Grid>
</DataTemplate>

I would really like to use the GUID in a more dynamic way as a key into a resource dictionary. I imagine it would look something like this (although obviously this won’t work): 

<DataTemplate>
  <Grid Height="Auto" Width="Auto">
    <ContentControl 
        Content="{StaticResource {Binding Path=ID}}" />
  </Grid>
</DataTemplate>

I thought I might be able to use a binding along with a value converter that uses FindResource() to look up the static resource. Unfortunately, my value converter does not receive a reference to the object on which the binding is set. It only gets the bound value (the GUID) and the type of the target dependency property. In order to call FindResource(), I need a reference to the actual target dependency object.

Is there an easy way to do this in WPF?

Thanks for any help you can provide!

Sincerely,
Jim
 


Hi Jim,

Yes, it can be frustrating that your value converter does not receive a reference to the target dependency object for the binding. Value converters were designed to be more generic in nature, allowing them to be used in scenarios that might not involve bindings. As such, they have no knowledge of the binding itself or the object on which it is set. That said, there are actually many cases where a value converter might desire this kind of contextual information. 

Your scenario is a prime candidate for a multibinding and multivalue converter. With a multibinding, you can actually supply your own reference to the target dependency object using one of the bindings, as follows:

<DataTemplate>
  <Grid>
    <ContentControl>
      <ContentControl.Content>
        <MultiBinding Converter="{StaticResource MyConverter}">
          <MultiBinding.Bindings>
            <Binding RelativeSource="{RelativeSource Self}" />
            <Binding Path="ID" />
          </MultiBinding.Bindings>
        </MultiBinding>
      </ContentControl.Content>
    </ContentControl>
  </Grid>
</DataTemplate>

 

In this case, the converter class must implement the IMultiValueConverter interface so that it can be used with the multibinding. Since we have conveniently passed in a Self reference as the first binding, we now have a reference to the target dependency object in our converter. The converter’s Convert method might look something like the following:

public object Convert(object[] values, Type targetType, 
    object parameter, CultureInfo culture)
{
  FrameworkElement targetObject = values[0] as FrameworkElement;
  if (targetObject == null)
  {
    return DependencyProperty.UnsetValue;
  }
  return targetObject.TryFindResource(values[1]);
}

 

I hope this helps!

Best regards,
Dr. WPF

The Doctor Is In

August 13th, 2007

Welcome to the online office of Dr. WPF.  This is my obligatory “Hello World” post.

I’ve managed (quite deliberately) to avoid the whole world of RSS for the past several years, as I really haven’t had much to say that I would deem especially blogworthy.  But lately, I’m spending more and more time answering questions about WPF, so it occurs to me that some of my knowledge might actually qualify as marginally interesting to a few of you.

So here goes…

If you have questions about WPF that you think might have broad appeal, please drop me an email and I will do my best to answer them.  If the volume becomes very large, I reserve the right to become very selective.

And thanks in advance for your patience as I learn the ins and outs of this thing we call the blogosphere.  🙂