WPF Round Table Part 1: Simple Pie Chart

Introduction

Click here to download code and sample project

Over the years I have been presented with many different situations while programming in WPF, which required a certain Control or class to be created to accommodate. Given all the various solutions I created throughout the years I thought it might be helpful to someone else. During this ongoing series I am going to post some of the more useful classes I have made in the past.

Simple Pie Chart

In one project I was assigned to redesign, there was data coming in that we wanted represented in the form of a pie chart. Initially, we simply displayed the information in the form of one out of many static pie chart images. A specific image would get selected based on what the percentage was closest. Although this solved our immediate needs I believed generating this with GeometryDrawing would make the chart much more accurate and should not be too difficult to create. My immediate goal was to try and represent some type of pie chart in XAML to get an idea of how it could be represented dynamically. Initial searching led to this solution involving dividing a chart into thirds. Following the example given will produce a subdivided geometric ellipse:

Pie Chart Example - 1

Programmatically Build Chart

Unfortunately, using strictly XAML will not work when attempting to create a pie chart dynamically. This is definitely a great starting point in how we could create this Control, but I needed a better understanding how to create geometric objects programmatically. Doing some more searching I came across this Code Project that describes how to create pie charts from code. My pie chart will be much simpler containing only two slices and taking in a percentage value to represent how the slices will subdivide. I still use an Image to represent how the geometry will be drawn and begin the creation of the root elements:

_pieChartImage.Width = _pieChartImage.Height = Width = Height = Size;

var di = new DrawingImage();
_pieChartImage.Source = di;

var dg = new DrawingGroup();
di.Drawing = dg;

Since I know my starting point of the pie will always be at the top I then calculate where my line segment will end (the PieSliceFillers are brushes representing the fill color):

var angle = 360 * Percentage;
var radians = ( Math.PI / 180 ) * angle;
var endPointX = Math.Sin( radians ) * Height / 2 + Height / 2;
var endPointY = Width / 2 - Math.Cos( radians ) * Width / 2;
var endPoint = new Point( endPointX, endPointY );

dg.Children.Add( CreatePathGeometry( InnerPieSliceFill, new Point( Width / 2, 0 ), endPoint, Percentage > 0.5 ) );
dg.Children.Add( CreatePathGeometry( OuterPieSliceFill, endPoint, new Point( Width / 2, 0 ), Percentage <= 0.5 ) );

My CreatePathGeometry method creates both the inner and outer pie slices using a starting point, the point where the arc will end, and a boolean for ArcSegment to determine how the arc should get drawn if greater than 180 degrees.

private GeometryDrawing CreatePathGeometry( Brush brush, Point startPoint, Point arcPoint, bool isLargeArc )
{
	var midPoint = new Point( Width / 2, Height / 2 );

	var drawing = new GeometryDrawing { Brush = brush };
	var pathGeometry = new PathGeometry();
	var pathFigure = new PathFigure { StartPoint = midPoint };

	var ls1 = new LineSegment( startPoint, false );
	var arc = new ArcSegment
	{
		SweepDirection = SweepDirection.Clockwise,
		Size = new Size( Width / 2, Height / 2 ),
		Point = arcPoint,
		IsLargeArc = isLargeArc
	};
	var ls2 = new LineSegment( midPoint, false );

	drawing.Geometry = pathGeometry;
	pathGeometry.Figures.Add( pathFigure );

	pathFigure.Segments.Add( ls1 );
	pathFigure.Segments.Add( arc );
	pathFigure.Segments.Add( ls2 );

	return drawing;
}

A better to visualize this is through a XAML representation:

<GeometryDrawing Brush="@Brush">
  <GeometryDrawing.Geometry>
	 <PathGeometry>
		<PathFigure StartPoint="@Size/2">
		   <PathFigure.Segments>
			  <LineSegment Point="@startPoint"/>
			  <ArcSegment Point="@arcPoint"  SweepDirection="Clockwise" Size="@Size/2"/>
			  <LineSegment Point="@Size/2"/>
		   </PathFigure.Segments>
		</PathFigure>
	 </PathGeometry>
  </GeometryDrawing.Geometry>
</GeometryDrawing>

And with that we are able to create quick an easy pie charts as shown here:

Pie Chart Example - 2

Multi Pie Chart

Although this is suitable for a two sided pie chart, but what if you wanted more? That process is pretty straight forward based off what we already created. By including two dependency properties to represent our collection of data and brushes, we only need to rewrite how my segments are created:

var total = DataList.Sum();
var startPoint = new Point( Width / 2, 0 );
double radians = 0;

for ( int i = 0; i < DataList.Count; i++ )
{
	var data = DataList[i];
	var dataBrush = GetBrushFromList( i );
	var percentage = data / total;

	Point endPoint;
	var angle = 360 * percentage;

	if ( i + 1 == DataList.Count )
	{
		endPoint = new Point( Width / 2, 0 );
	}
	else
	{
		radians += ( Math.PI / 180 ) * angle;
		var endPointX = Math.Sin( radians ) * Height / 2 + Height / 2;
		var endPointY = Width / 2 - Math.Cos( radians ) * Width / 2;
		endPoint = new Point( endPointX, endPointY );
	}

	dg.Children.Add( CreatePathGeometry( dataBrush, startPoint, endPoint, angle > 180 ) );

	startPoint = endPoint;
}

As you can see, the main difference is now we are accumulating the radians as we traverse the list to take into account any number of data objects. The result allows us to add any number of data items to our pie chart as shown here:
Pie Chart Example - 3

Conclusion

Although I did not get as much use for this class as I would have preferred, developing this helped me gain experience in manipulating geometry objects, which does not happen often enough.

Text On A Path With Alignment

Click here to download code and sample project

In past WPF projects, design specifications given by artists are sometimes challenging to attempt to implement. One scenario I have ran into multiple times was trying to display custom text around a curved object. Most of the time this problem was avoided by the artist providing the content as images, but, fortunately, this was only feasible because the text was finite and static. Recently I came across this same scenario again except this time the incoming text could be dynamic. The immediate reaction was to simply read the text as images stored in a folder provided by the customer. This solution tends to create problems in the future because:

  • The user must be familiar with some image editing tool
  • If not accustomed to any, then the user has to be trained
  • The user must be aware of the exact font, weight, and color the artist intended
  • The user must also have the same eye for lining up text as the original artist intended (which many tools can aid in)

With all these issues, it would be better to assume that if a user could get something wrong then they will, which will result in an application that seems off. Not happy with this path I decided to look into creating text on a path.

Fortunately, a majority of the work had already been developed by Charles Petzold described in his article Render Text On A Path With WPF.

The article provides a comprehensive description of his algorithm for placing text on a path. It is worth a read to get an in-depth understanding of how the algorithm works. To try and sum it up though, the algorithm uses a PathFigure object to shape the path the text will render and the class comes equipped with a method to help simplify calculations. In sizing the text font onto the path, the text is scaled to fit entirely on the length of the path. For the best performance, we render the text as DrawingVisual objects so they only need to be created once when the text changed. The result comes out as this:

Fantastic! This worked well for what I wanted, except for one problem; the text scaling. I knew the path I wanted my text to render, but not the length of the text since that could change dynamically. When attempting to apply this algorithm to a path I had in mind, the results were less than pleasing (red curve represents the path for the text):

I needed the text to render the same size despite the length of the path, but the current algorithm would require me to resize the path dynamically based on the size of the text. This did not seem reasonable, especially since I would prefer the text to rest on the center of the path.

So, in order to accomplish this the first thing I needed was a Dependency Property of type HorizontalAlignment to set the content alignment. Setting the alignment to Stretch will keep the original behavior of the algorithm by resizing the text to fit the path. Then we need another Dependency Property for font size, which will only get applied if the content alignment was not Stretch. Now, when calculating the text length we need to substitute our font size over the default 100

private void OnTextPropertyChanged()
{
    _formattedChars.Clear();
    _textLength = 0;

    if (!String.IsNullOrEmpty(Text))
    {
        foreach (char ch in Text)
        {
            var fontSize = ContentAlignment == HorizontalAlignment.Stretch ? 100 : FontSize;

            var formattedText =
                new FormattedText(ch.ToString(), CultureInfo.CurrentCulture,
                    FlowDirection.LeftToRight, _typeface, fontSize, Foreground);

            _formattedChars.Add(formattedText);
            _textLength += formattedText.WidthIncludingTrailingWhitespace;
        }

        GenerateVisualChildren();
    }
}

Then we move onto our TransformVisualChildren method and make sure the scaling factor stays at 1 since we no longer want the text to rescale to the path

private void TransformVisualChildren()
{
    ...
    var scalingFactor = ContentAlignment == HorizontalAlignment.Stretch ? _pathLength / _textLength : 1;
    ...
}

Since content alignment can be set as Center, or Right aligned, the initial progress will need adjusting to push the text further along the path

private void TransformVisualChildren()
{
    ...
    double progress = 0;

    switch (ContentAlignment)
    {
        case HorizontalAlignment.Left:
        case HorizontalAlignment.Stretch:
            progress = 0;
            break;
        case HorizontalAlignment.Center:
            progress = Math.Abs(_pathLength - _textLength) / 2 / _pathLength;
            break;
        case HorizontalAlignment.Right:
            progress = Math.Abs(_pathLength - _textLength) / _pathLength;
            break;
    }
    ...
}

And that is all we have to do since the scaling factor will be set to 1 if content is not stretched. Here is the result with content alignment set to Center. Also, you can see all the various alignments applied:

Although I was very satisfied with the results, a change in the scope of our project made this solution obsolete. Just another day in the life of a programmer.

PDFx – Property Dependency Framework – Part I, Introduction

The PDFx is a lightweight open source .NET library that allows developers to describe dependencies between Properties in declarative C# code. Once relationships are registered, the framework monitors property changes and ensures that the INotifyPropertyChanged.PropertyChanged event is fired for all directly and indirectly dependent properties in a very efficient way. The library is available for WPF, Silverlight, WinRT (Windows Store) and Windows Phone.

I’ve developed the PDFx as an InterKnowlogy RECESS project and published the source code and examples on codeplex.

In a series of blog posts I am going to cover the library’s most important features:

Introduction

The Property Dependency Framework (PDFx) is a lightweight library that allows you to capture the inherent relationship among the properties of your classes in a declarative manner. It is common in applications to have properties whose values depend upon the values of other properties. These properties need to be reevaluated when a change occurs in the properties on which they depend. For example, if “A” depends on “B” and “C”, we need to reevaluate the value of A whenever either B or C changes. Furthermore, B and C may not even be direct properties of the same class as that in which A exists. Instead, they may be properties of another class, or even properties of the items within a collection.

In large applications, complex chains of such dependencies can exist. Although C# gives us the INotifyPropertyChanged construct to send out a change notification (typically to UI elements), no framework to our knowledge has allowed the network of dependencies to be specified in a straightforward manner, with the proper change notifications issued automatically. The PDFx framework allows the dependencies of properties to be specified declaratively, building from them an internal network of dependencies for you. Changes to any property in the network are then propagated automatically and efficiently.

The PDFx framework establishes a simple pattern for capturing the relationships of data in applications, and removes tremendous amounts of “plumbing”. It also helps clarify and enhance the role of the View Model within MVVM, reducing the scattering of business logic throughout value converters. Once you’ve made use of PDFx, you will likely wonder how the gap it fills has gone unaddressed for so long.

Example

Since pictures tell better stories than words, I would like to demonstrate the benefits of this workhorse with a small example:

PDFX.png

The depicted algebra hierarchy represents a C# class. Green circles stand for Input Properties while purple circles indicate calculated properties. The arrows show the underlying math operations as well as the property dependencies.
As the developer of such a scenario, you’re responsible to ensure that all directly and indirectly dependent properties get reevaluated when an input property changes. Furthermore, for efficiency reasons, you also want to ensure that all unrelated properties do not get reevaluated.

If, for example, Property D1 changes, it is necessary to reevaluate C1, B1 and A1.
However, a change of D3 requires a reevaluation of only C2, B1, B2 and A1.

Using the PDFx, you don’t have to manually hardcode those relationships anymore but can rather rely on the library taking care of this job for you.
All you have to do is register the relationships in human readable code within the implementation of a property:

//....
public int A1
{
	get
	{
		Property(() => A1)
			.Depends(p => p.On(() => B1)
			               .AndOn(() => B2));
		
		return B1 + B2;
	}
}

public int B1
{
	get
	{
		Property(() => B1)
			.Depends(p => p.On(() => C1)
			               .AndOn(() => C2));
		
		return 2*C1 - C2;
	}
}

public int B2
{
	get
	{
		Property(() => B2)
			.Depends(p => p.On(() => C2)
			               .AndOn(() => C3));
		
		return -C2 + C3;
	}
}

public int C1
{
	get
	{
		Property(() => C1)
			.Depends(p => p.On(() => D1)
			               .AndOn(() => D2));

		return D1 + D2;
	}
}

public int C2
{
	get
	{
		Property(() => C2)
			.Depends(p => p.On(() => D3));

		return 3*D3;
	}
}

public int C3
{
	get
	{
		Property(() => C3)
			.Depends(p => p.On(() => D4)
			               .AndOn(() => D5));
		
		return D4 + D5;
	}
}
//....

Advanced Features

  • Dependencies on properties of external objects
  • Dependencies on ObservableCollections
  • Property Value Caching
  • (Deferred) Callbacks for Property Changes

Main Benefits

  • The dependency registration resides within the Property Getter implementation. This way you’re likely to notice immediately that an update of the registration is necessary when you change a property’s implementation.
  • The PDFx fires the PropertyChanged event only for Properties that are directly or indirectly dependent on the changed source property, thereby guaranteeing a high level of efficiency.
  • Properties whose data relies completely on the value of other properties do not need to encapsulate backing fields. They can be implemented solely in the Property Getter, thereby ensuring full integrity.

Make Portable Libraries Your Go-To Project Template

With the upcoming release of Visual Studio 2012, Portable Libraries will finally be built into the product. The 2012 iteration of Portable Libraries is much improved from the prior versions, adding not only new platforms (Windows 8 Metro) but greatly increasing the list of available framework library classes that can be used across the various platforms.

Continue reading

Microsoft Surface – Installing an App on V2

Previously, I wrote about porting my Surface Craps application from Surface v1 to v2.  Now that the app has been upgraded, here’s a short post on how to update the installer to work with v2.

There is not much different about the makeup of an application that is registered on the Surface between v1 and v2.  Your program binaries go in a directory, and then (new to v2) a SHORTCUT points the Surface shell to that directory.

Program Files

Unlike v1 that required you to install your program files in a specific “Program Data” sub directory, now you can install your program files to a directory of your choice – usually %ProgramFiles(x86)%.

CropperCapture113

Program Data Shortcut

Next, make your installer create a SHORTCUT to the directory where you install your program files, and place the shortcut in the Surface v2 directory:  C:\ProgramData\Microsoft\Surface\v2.0\Programs.

It’s important that this shortcut is to the DIRECTORY where your program files are, not a shortcut directly to the application .xml file.

Here’s how the Surface programs directory and shortcut properties should look.

CropperCapture115

That’s it – you should now see your application in the chooser when you run the shell.

Microsoft Surface – Porting from v1 to v2

A couple years ago, I wrote Surface Craps during RECESS to explore the Microsoft Surface table and APIs.  Now that Surface 2 is out, it’s time to upgrade the software to run on the new hardware.  This is the first in a series of blog posts about the process in upgrading from Surface v1 to v2.

Obviously this first requires that you have the Surface 2 SDK installed.  To start, I branched the project tree in TFS to make a v2 copy.

Open the project in VS 2010.  Update the project references.  The new referenced assemblies are in C:\Program Files (x86)\Microsoft SDKs\Surface\v2.0\Reference Assemblies.

  • Microsoft.Surface.dll
  • Microsoft.Surface.Presentation.dll
  • Microsoft.Surface.Presentation.Generic.dll

I was using Visual State Manager from the WPF Toolkit, and now it’s included in WPF 4, so I removed that reference as well.

Now we start the brute force process of fixing code that doesn’t compile.  Here’s a list of what I found.  Many of these changes are moving to WPF 4 in general, since it’s where we get most of the touch functionality in the Surface 2 environment.

Control Name Changes

Surface v1 Surface v2
SurfaceUserControl UserControl
SurfaceContentControl ContentControl

Event Handling Changes

Surface v1 Surface v2
ContactDown event use TouchDown
(Preview)ContactUp/Down use (Preview)TouchUp/Down
ContactDown event use TouchDown
(Preview)ContactUp/Down (Preview)TouchUp/Down
ContactChanged TouchMove
ContactEventHandler EventHandler<TouchEventArgs>
ApplicationActivated, etc. OnWindowInteractive, Noninteractive, Unavailable (see a default new Surface 2 project for an example of these event handlers)
ApplicationLauncher.Orientation ApplicationServices.InitialOrientation

Property / Method Changes

Surface v1 Surface v2
e.Contact.IsTagRecognized e.TouchDevice.GetIsTagRecognized( ). (add using statement for Microsoft.Surface.Presentation.Input to get the extension method)
e.Contact.Tag.Byte.Value e.TouchDevice.GetTagData().Series & .Value
e.Contact.GetPosition( ) e.TouchDevice.GetPosition( )
e.Contact.GetOrientation( ) e.TouchDevice.GetOrientation( )
ScatterViewItem.IsActive ScatterViewItem.IsContainerActive

Manipulation Processing

In Surface v1, you would use the Affine2DManipulationProcessor to handle gestures such as flick, rotation, scale, etc.  In v2, you just use the manipulation processing that’s provided by the WPF 4 UIElement.

Surface v1 Surface v2
On any elements that you want to track manipulations on, set IsManipuliationEnabled = true
BeginTrack( ) nothing to do in v2
Affine2DManipulationCompleted, … events UIElement.ManipulationCompleted, … events
e.Velocity.Length e.FinalVelocities.LinearVelocity.Length
e.TotalTranslation.X e.TotalManipulation.Translation.X

Resolution

That’s all I had to as far as API differences.  Next came the resolution differences. The Surface v2 display runs at 1920 x 1080, so if you have any UI that does not stretch or any hardcoded coordinate-based math in your software, it will have to be updated.

Tags

Surface v2 does not support Identity tags, but it does support Byte tags.  See the tag-related methods above for the API differences.

For Surface Craps specifically, I ran into a problem with the transparent dice we got from Microsoft for Surface v1. The dice have byte tags on them that are practically transparent, but have enough IR reflectivity to be picked up by the Surface v1 infrared cameras.  In Surface v2, the tags are recognized by interpreting the contact information using PixelSense technology, and something in that processing is not recognizing the mostly transparent tags on the dice.  I will continue to investigate this issue and write another post if I have any update.  For now – it’s a bummer that the physical dice do not work.

Installation

In a future post I will talk about the differences in what it takes to install your application in Surface v2…

 
 
 

SpeechRecognitionEngine Grammar Choices and Updating them Dynamically

The Microsoft Speech Platform provides a great speech recognition engine. I’ve been using it with the Microsoft Kinect to add voice command functionality to existing Kinect enabled WPF applications. The SDK is located here, and once installed you just need to add a reference to Microsoft.Speech.dll, which is located at C:\Program Files\Microsoft Speech Platform SDK\Assembly.

Static Choices
Once you have the SDK and assembly referenced, the process of specifying what words or phrases you want the SpeechRecognitionEngine to look for is extremely straight forward and easy. Just specify your collection of Choices, create a new GrammarBuilder and append the Choices to it, create a Grammar and provide it with the GrammarBuilder, and finally load that Grammar into the SpeechRecognitionEngine. You can then point the SpeechRecognitionEngine to your audio source and tell it to RecognizeAsync.

var sre = new SpeechRecognitionEngine(ri);
var currentChoices = new Choices();
currentChoices.Add("red");
currentChoices.Add("show blue square");

var gb = new GrammarBuilder
{
     Culture = _ri.Culture
};
gb.Append(currentChoices);

sre.LoadGrammar(new Grammar(gb));

Dynamic Choices
If you know all of the possible command choices from the beginning and never need them to change, then this is as far as you need to go. I, however, wanted to be able to change what choices were valid based on what area of the application I was in. I had hoped it would be as simple as adding and removing choices for the collection, but there isn’t any remove functionality in Choices, GrammarBuilder, or Grammar. On the SpeechRecognitionEngine I did find an UnloadGrammar method so I figured I could just keep a collection of my currently valid choices, create a new Grammar from those, unload the old Grammar, and then load the new one. When I ran the application I ran into some very weird results. Calling UnloadGrammar would take a very long time to execute (it took 3 minutes for one try). Once it got past that point loading the new grammar worked, but the amount of time it was taking was unbearable and I would not be able to use it if there was always the possibility of the application freezing up for that long just to change the available audio choices. So after a long time searching I finally decided to see what MSDN had to say about the UnloadGrammar and LoadGrammar methods and found this page. It is for Office 2007 R2 but the example it provided put me on the right track.

It turns out that when the SpeechRecognitionEngine is running, any changes to the grammar need to occur when the engine is ready for the changes. To get the engine ready you need to call RequestRecognizerUpdate and pass a custom object (that contains what action you want to do and the related data) into the method as a UserToken.

sre.RequestRecognizerUpdate(new UpdateGrammarRequest
								{
									RequestType = GrammarRequestType.UnloadGrammar,
									Grammar = _currentGrammar
								});
sre.RequestRecognizerUpdate(new UpdateGrammarRequest
								{
									RequestType = GrammarRequestType.LoadGrammar,
									Grammar = _currentGrammar
								});

You also need to subscribe to the RecognizerUpdateReached event on the engine, and in that event handler you can call the UnloadGrammar and LoadGrammar methods which will then execute immediately.

private void RecognizerUpdateReached(object sender, RecognizerUpdateReachedEventArgs e)
{
	var request = e.UserToken as UpdateGrammarRequest;
	if (request == null)
		return;
		
	switch (request.RequestType)
	{
		case GrammarRequestType.LoadGrammar:
			sre.LoadGrammar(request.Grammar);
			break;
		case GrammarRequestType.UnloadGrammar:
			sre.UnloadGrammar(request.Grammar);
			break;
		default:
			throw new ArgumentOutOfRangeException();
	}
}

By doing this, you still end up with a tiny bit of lag between calling RequestRecognizerUpdate and having the RecognizerUpdateReached event fire, but it is only ever a couple seconds instead of minutes.

Snoop 2.7.0

This post is long overdue. I have written about Snoop for WPF a couple times, and it’s been a while since I gave an update.

Back in September, we published v2.7.0 (release announcement). One of the coolest new features is the ability to drag and drop a cross-hair to the app you want to snoop. You no longer have to wait for the list of applications to refresh.  We added a DataContext tab and various bug fixes.

CropperCapture35

I’ve been spending a bit of my RECESS time lately getting back into contributing to the code base. We have some really cool features in the works — I’ll post again when the next version hits the streets.

Prism 4, MEF and the CompositionInitializer

So I have been using MEF (Managed Extensibility Framework) for a while now on most of my WPF projects. Lately, I have been really getting a lot of use out of Prism 4.0 as well and utilizing the built in MEF with the MefBootstrapper.

One of the things that I always found a bit troublesome however was what to do when you need a non-exported class to satisfy its imports from MEF. This came up on a recent project, as I was using the IEventAggregator from Prism, thought it would be useful to have it in classes that may not come from MEF- i.e. classes that are new’ed up depending on the business logic dictated. Now, the true MEF heads may say, ‘Nooooo! That’s not what MEF is for!’. But I thought I would see how it worked anyway.

To solve this, one approach was to pass in my IEventAggregator to my class through the constructor, but this didn’t seem too elegant. What if I need other imports besides the IEventAggregator? Then potentially I need to pass in more and more stuff to the constructor.

What I really needed, was some way to tell the class that it has imports it needs to satisfy, and notify that class that it needs to check the already existing container for this. This is where the CompositionInitializer comes in. One problem with that is that the CompositionInitializer was designed for Silverlight, and my application is MEF. But, no worries, Glenn Block had anticipated my need and kindly written a WPF CompositionInitializer, to be found here. Thanks Glenn. And in addition, I found lots of other great info from Reed Copsey’s site. Thanks Reed.

So I placed my CompositionInitializer in my non-exported class in the constructor:

// No export here
public class MyClass
{
	public MyClass()
	{
		CompositionInitializer.SatisfyImports( this );
	}

	[Import]
	private IEventAggregator EventAggregator { get; set; }
}

But when I ran the code, even though I had a valid import for my IEventAggregator, none of my messages were being received. A bit of googling brought me here. Aha! Simply placing my CompositionInitializer.SatisfyImports( this ) in the constructor is insufficient. How, after all, does the CompositionInitializer know what container you are using? I was so used to MEF magic that it hadn’t occurred to me that CompositionInitializer needs to have its container set.

By adding the following line to my BootStrapper file in a location that gets called after CreateShell():

CompositionHost.Initialize( Container );

My CompositionInitializer was now armed with the appropriate container, and everything worked great in the constructor. Now I was able to new up an instance of any class and satisfy its imports against my Container.

XamlReader, Loose ResourceDictionary Files, and the ParserContext

In a few WPF projects that I have been on I have needed to load in loose ResourceDictionary files to provide different runtime styling. When there isn’t any external content being referenced (ie. images, videos, etc…) it is as simple as calling XamlReader.Load and then merging the dictionary into the application’s resources:

var resourceDictionary = XamlReader.Load(fileStream) as ResourceDictionary;
if(resourceDictionary != null)
{
    Resources.MergedDictionaries.Add(resourceDictionary)
}

When external content is being referenced there is the possibility that the XamlReader won’t be able to find those files, even if they are in the exact same folder as the ResourceDictionary files. To solve this issue, you will need to create a ParserContext and set its BaseUri to the root folder containing the files. For example, if the ResourceDictionary and content files are located in a folder called RuntimeResources, which is in the same folder as the application’s exe, then the BaseUri needs to point to that RuntimeResources folder. Then when the XamlReader loads the ResourceDictionary, it uses the provided ParserContext to know where to look for the actual files. NOTE: In the ResourceDictionary you will still need to include the root folder (RuntimeResources) at the beginning of the uri otherwise it will look in the parent directory for the desired file.

Below is the related code:

C#

var applicationDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if(!String.IsNullOrEmpty(applicationDirectory ))
{

    var runtimeResourcesDirectory = Path.Combine(applicationDirectory , "RuntimeResources");
    var pc = new ParserContext
    {
        BaseUri = new Uri(runtimeResourcesDirectory , UriKind.Absolute)
    };
    if(Directory.Exists(runtimeResourcesDirectory ))
    {
        foreach (string resourceDictionaryFile in Directory.GetFiles(runtimeResourcesDirectory , "*.xaml"))
        {
            using (Stream s = File.Open(resourceDictionaryFile, FileMode.Open, FileAccess.Read))
            {
                try
                {
                    var resourceDictionary = XamlReader.Load(s, pc) as ResourceDictionary;
                    if (resourceDictionary != null)
                    {
                        Resources.MergedDictionaries.Add(resourceDictionary);
                    }
                }
                catch
                {
                    MessageBox.Show("Invalid xaml: " + resourceDictionaryFile);
                }
            }
        }
    }
}

Resource Dictionary

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
			    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

	<ImageBrush x:Key="LogoImage"
			  ImageSource="RuntimeResources/logo.png" />

</ResourceDictionary>

Now you’ve got the ability to change your WPF application’s styling at runtime.