I recently took on a Windows Universal project. As with any multiple device project one of the goals is to share as much as possible to avoid writing the same code twice.

The is no conditional compile in XAML, so that means that separate XAML files are needed in the cases where complete sharing is not possible. Luckily the Windows Universal project structure is set up so that all you need to do to share a XAML file is move the file into the Shared folder/project.

Styles are the appropriate way of providing a consistent styling across multiple pages /sections of the application, so it makes sense to try and place those in a common area. However, there will be some styles which will be specific to the Windows or Windows Phone projects. The tricky part is finding a way to share the bulk of the style, except for those pieces which are specific.

My first thought was to have a SharedStyles.xaml in the Shared folder, and a PlatformSpecificStyles.xaml in each Windows and WindowsPhone directory. Then in the App.xaml include first the shared files followed by the specific files. Something like this:

ResourceSharing.Shared\SharedStyles.xaml

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

 <Style TargetType="HubSection" x:Key="HubSectionStyle">
  <Setter Property="Background" Value="Pink" />
 </Style>
</ResourceDictionary>

ResourceSharing.Windows\PlatformSpecificStyles.xaml

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

 <Style TargetType="HubSection" BasedOn="{StaticResource HubSectionStyle}">
  <Setter Property="Foreground" Value="Purple" />
 </Style>
</ResourceDictionary>

ResourceSharing.WindowsPhone\PlatformSpecificStyles.xaml

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

 <Style TargetType="HubSection" BasedOn="{StaticResource HubSectionStyle}">
  <Setter Property="Foreground" Value="Blue" />
 </Style>
</ResourceDictionary>

ResourceSharing.Shared\App.xaml

<Application
    x:Class="ResourceSharing.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 <Application.Resources>
  <ResourceDictionary>
   <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="SharedStyles.xaml" />
    <ResourceDictionary Source="PlatformSpecificStyles.xaml" />
   </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
 </Application.Resources>
</Application>

However, it turns out that doesn’t work. In order to ResourceDictionary A to reference a resource from ResourceDictionary B, the ResourceDictionary A needs to include the ResourceDictionary B itself. So the end result ended up looking like this:

ResourceSharing.Shared\SharedStyles.xaml
unchanged

ResourceSharing.Windows\Styles.xaml (renamed from PlatformSpecificStyles.xaml)

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

 <ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="SharedStyles.xaml" />
 </ResourceDictionary.MergedDictionaries>
 
 <Style TargetType="HubSection" BasedOn="{StaticResource HubSectionStyle}">
  <Setter Property="Foreground" Value="Purple" />
 </Style>
</ResourceDictionary>

ResourceSharing.WindowsPhone\Styles.xaml (renamed from PlatformSpecificStyles.xaml)

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

 <ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="SharedStyles.xaml" />
 </ResourceDictionary.MergedDictionaries>
 
 <Style TargetType="HubSection" BasedOn="{StaticResource HubSectionStyle}">
  <Setter Property="Foreground" Value="Blue" />
 </Style>
</ResourceDictionary>

ResourceSharing.Shared\App.xaml

<Application
    x:Class="ResourceSharingHubApp.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 <Application.Resources>
  <ResourceDictionary>
   <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="Styles.xaml" /> <!-- both Shared and PlatformSpecific -->
   </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
 </Application.Resources>
</Application>

Hope that helps

This blog was cross posted on the Crafting Bytes blog at Resource Sharing in Windows Universal Apps

This week I was called on to do a very strange on-site custom course. They basically couldn’t decide on any one topic so they wanted me to talk a little bit about everything, mainly concentrating on:

  1. Advanced Windows Forms
  2. Windows Communication Foundation
  3. Unit Testing

As I have covered Windows Communication Foundation many times, and I didn’t have quite enough time to do unit testing any justice, the most interesting of the talks (I thought) was Windows Forms. We covered MDI, Notify Icons, and to my surprise had an interesting eventing discussion. Someone had asked about the difference between WPF and Windows Forms. I was trying to describe how they can be very similar but if you program WPF the right way how very different they really were and how complicated WPF was compared to Windows Forms. As part of this description I mentioned that Windows Forms has only the direct event model, but WPF has both bubbling and tunneling in addition to the direct model. Again someone raised their hand and asked if there was no way to simulate the bubbling model that they had in MFC (and WPF) using Windows Forms. He mentioned that they were having problems with coupling between components. I told them that the Client Application Block had something like this built in. He said that they found the CAB a little too heavy, and I agreed. I told him I would think more about it and get back to him tomorrow.

When I got back to the hotel that evening I started thinking about it and realized that there was a way to simulate it using a publish and subscribe type mechanism. This is basically a lightweight version of what the CAB clock does. I named my class the same as theirs as a form of flattery.

When you specify that you want to subscribe to a button click using the following syntax.

EventBroker.Instance.Subscribe(this, typeof(Button), "Click", OnButtonClick);

The EventBroker basically just walks the tree of controls recursively searching for controls of the type button, and then adds itself as a subscriber to that button. If someone else in the hierarchy also subscribes for button clicks the EventBroker knows which subscriber to call first. If the inner subscriber handles the event then the outer subscriber never sees the event, just like bubbling.

Best of all, you only need to drop in this one file, and away you go.
Here is the file in its entirety:

using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;

namespace WindowsFormsApp
{
	// helper method to make the code below more readable
	public static class ControlExtensions
	{
		public static bool IsParentOf(this Control c, Control other)
		{
			Control parent = other;
			while (parent != null)
			{
				if (c == parent)
					return true;
				parent = parent.Parent;
			}
			return false;
		}

	}

	public class EventBroker
	{
		class EventHolder
		{
			public Control Control { get; set; }
			public EventHandler<BubblingEventArgs> EventHandler { get; set; }
		}

		// singleton
		public static readonly EventBroker Instance = new EventBroker();

		readonly Dictionary<Control, List<EventHolder>> subscribers = new Dictionary<Control, List<EventHolder>>();

		public void Subscribe(Control c, Type type, string eventName, EventHandler<BubblingEventArgs> callback)
		{
			SubscribeRecursive(c, c, type, eventName, callback);
		}

		private void SubscribeRecursive(Control subscriber, Control c, Type type, string eventName, EventHandler<BubblingEventArgs> callback)
		{
			if (type.IsInstanceOfType(c))
			{
				// check to see if this eventName exists and subscribe
				Debug.WriteLine(string.Format("{0} is of type {1}", c.Name, type.Name));

				List<EventHolder> list;
				var newHolder = new EventHolder
				{
					Control = subscriber,
					EventHandler = callback,
				};

				// do we already have a subscriber for this object?
				if (subscribers.TryGetValue(c, out list))
				{
					// walk through the list trying to find where to insert this subscriber
					bool inserted = false;
					for (int cnt = 0; cnt < list.Count; cnt++)
					{
						EventHolder holder = list[cnt];

						// uses the extension method above
						if (holder.Control.IsParentOf(subscriber))
						{
							list.Insert(cnt, newHolder);
							inserted = true;
							break;
						}
					}
					// if they weren't inserted add them at the end
					if (!inserted)
					{
						list.Add(newHolder);
					}
				}
				else
				{
					// this is a new object, subscribe to its event
					EventInfo eventInfo = c.GetType().GetEvent(eventName);
					eventInfo.AddEventHandler(c, new EventHandler(OnEvent));

					// then create a new list of subscribers keyed to this object
					list = new List<EventHolder> {newHolder};
					subscribers.Add(c, list);
				}
			}

			// now recursively subscribe
			foreach (Control child in c.Controls)
			{
				SubscribeRecursive(subscriber, child, type, eventName, callback);
			}
		}

		public void OnEvent(object sender, EventArgs e)
		{
			// grab the list of subscribers for this control
			List<EventHolder> list = subscribers[(Control)sender];

			foreach (EventHolder holder in list)
			{
				Debug.WriteLine(string.Format("About to call {0}", holder.Control.Name));

				// call this subscriber
				var handledArgs = new BubblingEventArgs {InnerArgs = e};
				holder.EventHandler(sender, handledArgs);

				// if they handled the event don't propogate further
				if (handledArgs.Handled)
					break;
			}
		}
	}
}

Don’t get me wrong, I love WPF. I think it is a great technology, and I will continue to leverage it on UI applications that I happen to write. That said, WPF could have definitely benefited from an architecture and consistency team like they had for the BCL in the beginning days of .NET itself. It feels too much like WPF was designed like a bunch of individuals rather than a team. So without further ado here is my list of top ten problems in WPF.

#10 – DockPanel.Dock property does not have a value of Fill. You might be asking, Yeah? So what? Well, instead it assumes by default that the LastChildFill=true. And what that means is instead of laying out the Xaml as top, middle, bottom, or even left, middle, right, you have to lay it out as top, bottom, middle and left, right, middle. Just less readable than it should be. In addition it makes switching from one panel to another difficult. Let’s say you want to move the StackPanel to a DockPanel? Well you not only have to add the properties, you also have to move things around, to get the filled element in the correct position.

#9 – RelativeSource binding is not powerful enough and is too verbose Do you ever assign RelativeSource to anything but a RelativeSource? Can you? So, why do I have to specify it twice? Why not just Source={Relative}? Why isn’t Self just a separate MarkupExtension? Why do I have to go through the whole RelativeSource binding just to get to myself? Also while we are on the subject – what happened to Sibling binding?

#8 – No overriding parts of templates. If there is one thing we should have learned in Software Engineering by now – it is the tried and true principle of DRY (Don’t repeat yourself). But in order to modify a template you have to grab the existing template paste a copy of it and start hacking away. It doesn’t matter if you only need to change one little aspect, you need the entire template. And some of these templates can get really large – like NavigationWindow or Expander for example.

#7 – The Grid is cumbersome to define and refactor. This one really bugs me. In order to create a grid that has multiple children, one needs to define a set of row definitions and column definitions. Annoying, but not the real problem. The real problem is that the children don’t auto-increment. Each child must specify the Grid.Row and Grid.Column that they need to be placed in. There are a couple of problems here: the first is it is just a lot of typing. But the more insidious problem is that in order to later add a column or a row all of the subsequent columns or rows must be incremented. Contrast this with the way HTML tables work – the new column or row can be added in later and no code has to be altered in the process. I understand the power of the grid as it has been specified. However, it would be nice if that power came with some simplicity. To fix this we need four more properties on the grid itself: NumberOfRows, NumberOfColumns, AutoIncrementColumn, and AutoIncrementRow – where the last two are mutually exclusive (you can only set one). Problem solved, no need to declare the lengthy Row and Column specifications, or the Row and Column specifications (unless you are actually doing something which requires the complexity)

#6 – There is NO Rule #6 (couldn’t resist – I am a big Monty Python fan). Actually the problem is, Validation is per binding. What this means is that there is no good way of doing validation where the business rule encompasses more than one piece of data. For example if there are two TextBoxes and the sum of the values is greater than some amount. All of that logic has to be coded in a custom way.

#5 – No way of overriding Equals for ItemsSource and SelectedItem. It is pretty amazing how often I run into this one, and how easy the fix would be. When you set the ItemsSource to be a collection obtained from some ORM layer, and then in another context you grab another instance of one of the items in your ItemsSource you can’t simply set the SelectedItem equals to that new instance, unless it happens to be an immutable object that overrides Equals. In looking for a solution for this many people are recommending that if you control the object (not always the case) you should override Equals. But this is a really bad idea if the identifying properties can change. The right way to fix it is to search through the items from the ItemsSource and select one whose properties match the object you have retrieved. But it would be lovely if we had a way of setting a method to determine equality just like we have ways of sorting, grouping and filtering on the CollectionViewSource.

#4 – Observable list problems. If you do any binding to collections you have probably come across the ObservableList. Lovely collection, it fires events when changed. There are only two drawbacks that make this collection hard to use in some situations: 1) It can only be changed (item added or deleted) on the dispatcher thread 2) You can’t change the collection in response to a collection changed event These two problems are extremely annoying and result in convoluted workarounds

#3 – No easy way of asking what is the visual representation for this item if it is being represented by a DataTemplate. Or what is the item for this visual representation for that matter. Yes it can be done. But it involves some yucky fragile code. It would be great if the ItemsControl base class was able to add a method which wrapped this logic – something like listBox.GetVisualFromItem(someObject);

#2 – Death by a thousand paper cuts (inconsistencies): Many of these examples were taken from Adam Nathan’s excellent book “WPF Unleashed”. There are good reasons for all of these, and in some cases they are an absolute necessity. I am just saying that a newcomer can be quickly overwhelmed by such details. Here are some inconsistencies that new users may face when beginning XAML, followed by a question they might ask when confronted by the inconsistency.

None of these thing are major items. In fact most of them make perfect sense once you understand what is going on. But it all adds up to a learning curve that is incredibly steep.

#1 – The ComboBox absolutely sucks ComboBox doesn’t support a TextChanged event, or a SelectionChang*ing* event. These are two absolutely essential elements of the ComboBox, which means you almost always have to create your own. There are a couple of other minor issues like: IsEditable and IsReadonly are confusing (see above). In addition there is no good way to bind if you are editable but your ItemsSource is bound to a property. To make matters worse, when you try and fix these problems by subclassing ComboBox you will find that most of the important methods that you would love to be able to override are actually marked internal.

[Update 2010-05-25] If I had to do this list over again, I would find room for the troublesome fact that ICommand is in the PresentationCore assembly and the System.Windows.Input namespace. What is the problem here? Well I like to make it easy for developers to tell the difference between the View and the ViewModel. Ideally the ViewModel would contain a number of Commands, but that requires knowledge of the UI layer that it was built for. One could say only the PresentationCore assembly and that namespace are allowed in the ViewModel. But once they are included, it is pretty easy to “accidentally” include other UI aspects into the ViewModel as well.