Validation Interfaces

IValidationRuleProvider

Rules can be provided to a Validator in two ways. The first is to simply register an individual ValidationRule with the Validator using the RegisterRule() method.

SampleAsyncRule asyncRule = new SampleAsyncRule(3000);
validator.RegisterRule(this, asyncRule);

IValidationRuleProvider The second is to nominate an IValidationRuleProvider by adding it to the RuleProviders collection property. A RuleProvider is responsible for providing zero or more ValidationRules to the Validator when it is asked to validate an object instance for the first time. An example implementation is the EntityRuleProvider class which creates validation rules  by using TypeDescriptor methods to iterate over all Property and Type level Attributes searching for those that implement the IAttributeRuleProvider interface (see below).

// Create an EntityValidator for each business model class that requires validation.
EntityValidator holidayValidator = new EntityValidator();
// Register the entity with the validator - this will create all the necessary rules as
// determined by the rule Provider.
holidayValidator.RegisterEntity(_holiday, new EntityRuleProvider());

Alternatively a different IValidationRuleProvider could be used so that rather than defining validation rules declaratively using .NET Attributes they could be extracted from some external source, for example an XML config file.

IValidationValueProvider

IValidationValueProvider This interface is used by the ValidationRules themselves. When a rule is Validated by a Validator it is passed a single value. This value will be the instance that the Validator has been asked to Validate. For example an EntityValidator may use INotifyPropertyChanged to validate a business entity on every property change – and the business entity instance would be passed to the ValidationRule.

Implementations of the IValidationValueProvider allow the value that is to be validated to be derived immediately prior to the rule’s execution. If no IValidationValueProvider is assigned to the ValidationRule it will simply use the value passed by the Validator (e.g. the business entity). A very simple IValidationValueProvider is the PropertyValueProvider which simply uses a PropertyDescriptor to resolve the property value from the instance being validated for rules that act on a Property rather than a Type.

This could be extended for example by having a ControlValueProvider that extracts the value from an unbound User Interface control based on the type of control. This would allow validation at the control level in the rare cases where validation wasn’t being performed on Controller/Presenter elements.

In addition to providing a value this interface is also responsible for identifying the context in which any errors occurred. More on this below.

IAttributeRuleProvider

Each custom Attribute class is responsible for creating its own ValidationRule(s) via this interface. This makes declaratively defining new custom ValidationRules very easy.

IAttributeRuleProvider

The code below shows how the EntityRuleProvider implements IValidationRuleProvider.GetRules by making use of the IAttributeRuleProvider.

public ICollection<ValidationRule> GetRules(object value)
{
List<ValidationRule> rules = new List<ValidationRule>();
// Get a list of all properties defined on this object
    PropertyDescriptorCollection propertyDescriptors = TypeDescriptor.GetProperties(value);
// Iterate through the properties and pull of all the attribute defined validation rules
    foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors)
{
foreach (Attribute attribute in propertyDescriptor.Attributes)
{
IAttributeRuleProvider attributeRuleProvider = attribute as IAttributeRuleProvider;
if (attributeRuleProvider != null)
{
ValidationRuleCollection newRules = attributeRuleProvider.GetRules(value, propertyDescriptor);
foreach (ValidationRule newRule in newRules)
{
newRule.ValueProvider = new PropertyValueProvider(propertyDescriptor);
newRule.DefaultMessageParameters.Add("value", propertyDescriptor.DisplayName);
rules.Add(newRule);
}
}
}
}
// Now pull the attribute defined validation rules off the class itself.
    foreach (Attribute attribute in TypeDescriptor.GetAttributes(value))
{
IAttributeRuleProvider attributeRuleProvider = attribute as IAttributeRuleProvider;
if (attributeRuleProvider != null)
{
ValidationRuleCollection newRules = attributeRuleProvider.GetRules(value, null);
foreach (ValidationRule newRule in newRules)
{
newRule.ValueProvider = null;
newRule.DefaultMessageParameters.Add("value", value.GetType().Name);
rules.Add(newRule);
}
}
}
return rules;
}

Note that by using PropertyDescriptor.DisplayName we get the “friendly” name of the property as can be provided via the System.ComponentModel.DisplayName attribute. This is important because its gets passed in as a “token” for optional use by the ValidationRule’s message, e.g. “The {value} is mandatory.” would automatically resolve {value} to the DisplayName.

ValidationContext

This abstract class is used to determine the context in which a ValidationRule failed. There are three concrete Context’s so far as shown below.

ValidationContext

Again, if User Interface Control level validation was required it would be easy to add a ControlContext class deriving from ValidationContext. One of the things that the ValidationContext is used for is displaying visual cues in the user interface to  indicate validation failure. For example a rule could be executed in the business tier (on an application server) and transmitted back to the client. The user interface can then use data binding (or some other method) to match the context to a relevant user interface element.

Validation Revisited

This will be the first of a few posts that attempt to explain how I’m going about building my first prototype WPF application. Everything I’ve built thus far in WPF has really just been code fragments to try out a small subset of the WPF architecture. The goal of this is to create for myself a WPF application framework designed for building typical line of business (LO applications.

I’m going to start with the Validation framework that I’ve blogged about previously and also show how similar concepts applied to the validation can be used to reduce the amount of XAML I have to write in other areas.

Goals

Goal Translation
Provide responsive, non-intrusive and comprehensive validation of data. Immediate feedback where performance permits.
No message boxes!
Async processing option.
Property level, control level, class level validation.
Reduce the amount of business logic duplicated in the presentation layer by harnessing a rich meta-data model exposed by the business layer. Define meta-data on business logic preferably using attributes.
I consider end-user field names to be business meta-data.

Features

  1. Validation logic is layer independent, it doesn’t rely on base business classes, or any presentation framework elements. (Why do the WPF Validation classes like ValidationResult and ValidationRule live in the System.Windows namespace branch in PresentationFramework.dll?)
  2. Validation Rules can be defined using declarative markup (attributes) or “registered” against an entity at runtime. There is no mandatory requirement for a class being able to participate in the validation. That is to say – no required base business entity, no mandatory interfaces etc.
  3. Provides various extensibility points for easily defining new rules with all the same features.
  4. Validation results allow for rich information to be provided about the rule violation and the context in which it occurred. For example, the results are tied back to the property, instance or control responsible. This happens regardless of whether the rule violation was as a direct result of a control value changing, or whether it was due to a business rule running on either client or server.

Validation Rules

WorkingArea The basis for this ValidationEngine is the abstract ValidationRule class. Derived classes are responsible for validating a provided value. If the value does not violate the rule then a standard “passed” result is returned. Otherwise the rule is responsible for constructing a message that describes why the value didn’t pass.

The message can be the default text defined against the class or one that is defined specific to the validation instance. Either method has the opportunity to use standard tokens that are defined by the rule, or derived from the context. For example a ValidationRule applied to a class property will have the DisplayName of the property made available to it for construction a standard or overridden message, e.g. “The {property} is a mandatory field and requires a value to be entered.”

Similar to the System.Windows.Control.ValidationRule class the  abstract Validate method is where the actual validation occurs. The signature for Validate is the same making it easy to create a generic wrapper to convert any existing ValidationRule for use in this framework.

The ValueProvider property is a reference to an object (implementing IValidationValueProvider) that is responsible for providing a value to the ValidationRule when executed. The simple scenario here is a provider that uses a PropertyDescriptor to get a value of the property to which the ValidationRule is registered when performing validation against an instance.

Priority is used to define the default order in which rule violations should be ranked.

Severity is used to determine whether the rule violation is indicative of an error, a warning, a hint etc. This is also used to determine whether the violation will trigger IsValid on the Validator.

Applying Rules via Attributes

IAttributeRuleProvider The easiest method of assigning ValidationRules is to decorate the business entities with attributes (a very common approach). This is made very simple by having an IAttributeRuleProvider interface. Any attribute class that implements this interface is responsible for generating one or more ValidationRules via its GetRules method that will be applied against the entity itself or an entity property (depending on where the attribute was placed).

For example, say you create a new Attribute that allows for string properties to be further defined by nominating them as URLs, e-mail addresses, phone numbers etc. By having your Attribute implement IAttributeRuleProvider you could ensure that a ValidationRule is automatically assigned by the AttributeRuleProvider. In this example it may be that it simple returns a RegEx ValidationRule which the regular expression specific to the string type.

Performing the Validation

IValidator The Validation of ValidationRules is performed by an IValidator. There are currently two types of IValidators, inheriting from a common abstract Validator class. The EntityValidator which can validate rules against a class instance and uses the INotifyPropertyChanged interface to optionally keep executing the rules. The other is a FormValidator which extends the base implementation with knowledge about UI elements. For instance it allows validation to be performed against an unbound control, and has the capability of tying business properties back to any control that they may be bound to for error notification.

IValidators can be nested. In this scenario when they are asked to Validate they will also call Validate on each of their child IValidators. Also there IsValid property will only become true if all child IValidators also have their IsValid property being true. A common usage here might be to have a FormValidator that is responsible for validation form specific rules which has child IValidators for each business entity enable for updating.

A ValidationValueProvider is responsible for providing the Validator with both a value to test and a context for that value. The value is passed to the ValidationRule for validation and the context is attached to any violation result.

A Validator is created that is responsible for keeping track of the current validity of all objects that are registered with it. The Validator gets its rules from one or more rule providers that implement IValidationRuleProvider.

Validating in the Business Layer

This is easy, there are two simple options.

First choice is to create an EntityValidator instance and call the RegisterEntity method on it to register your business class that has been decorated with IAttributeRuleProvider attributes. Then call Validate and check use the IsValid and Ful
lResults properties to determine success/failure. Using this method it is possible for the business class to have no knowledge of the validation logic.

Second choice is to create a base business entity class that has this functionality built it (or extend your existing base business entity class). This could then provide either direct access to an instance EntityValidator, or simply expose the properties you require as wrappers around the internal EntityValidator.

Visualising Validation Results in the Presentation Layer

ErrorTemplate

This is in a state of flux. Currently I’m using the System.Windows.Controls.Validation class to highlight errors using its ErrorTemplate attached property. I started using IDataErrorInfo but it seemed to be more of a hindarance than anything. The only real benefit was its integration with the Validation properties via DataErrorValidationRule, but initial results seem that I can achieve this a different way.

ValidationPanel

A very simple custom control that derives from ItemsControl. Its ItemsSource is linked to the FullResults property of the forms/presenters top level IValidator. How the errors are displayed is really just dependent upon the styling applied to the control. However, I’ve added some very minimal functionality to start with. For example, clicking on a Validation Result whose context can be linked to a bound control will cause that control to receive focus.

Binding Exceptions

In my framework Binding exceptions are caught by the FormValidator. This means that if data is entered into a control that is not possible for the Binding to coerce into the bound source the FormValidator will become IsValid=False even though the business entity Validator to which the control is bound may remain IsValid=True. This felt like the obvious choice – the value never gets to the underlying business entity – yet the form still needs to notify of the error and prevent a Save etc. since what appears on screen (the bound control retains the un-bindable value) is not reflective of the model.

What’s left to be done?

Lots.

So where is the code?

Its coming soon…

How to get a list of Bindings in WPF?

Tonight I was struggling with how to get a list of Bindings defined within a WPF form. Why do I want to do this? Well there are two reasons.

  1. I want to be able to evaluate each binding and use the meta-data defined on the business entity to “decorate” the bound control. For example, a description of the business entity property (defined using an attribute) could be applied as the default tooltip on the control to which it is bound. This can (and in the WinForms world I have) be taken much further to determine the data source for lookup fields, label text, maximum input lengths or masks etc.
  2. If I validate a business entity and it returns a list of validation errors I want to be able to use the validation “context” (the instance type and property name) to be able to highlight the relevant bound control (if any) as being in error.

In WinForms determining all Bindings for a given top level control is reasonably straight forward by iterating through the controls and examining the BindingContext’s CurrencyManager’s Bindings collection. Normally a WinForm will only have a small number (e.g. 1) BindingContext that is inherited by child container controls.

In WPF I couldn’t find anything obvious. There is a likely sounding BindingOperations static class which provides several helper methods but none seem to do the trick.

The solution I ended up with before resorting to Google was to use reflection as follows…

private static ValidationBindingContext GetBindingForProperty(Type boundType, string boundPropertyName, 
FrameworkElement root) { foreach (FrameworkElement element in LogicalTreeHelper.GetChildren(root).OfType<FrameworkElement>()) { FieldInfo[] properties = element.GetType().GetFields(BindingFlags.Public | BindingFlags.GetProperty |
BindingFlags.Static | BindingFlags.FlattenHierarchy); foreach (FieldInfo field in properties) { if (field.FieldType == typeof(DependencyProperty)) { DependencyProperty dp = (DependencyProperty)field.GetValue(null); if (BindingOperations.IsDataBound(element, dp)) { BindingExpression bindingExpression = BindingOperations.GetBindingExpression(element, dp); if (boundType == bindingExpression.DataItem.GetType()) { if (boundPropertyName == bindingExpression.ParentBinding.Path.Path) { return new ValidationBindingContext(bindingExpression, element as UIElement); } } } } } // Not found so check all child elements ValidationBindingContext bindingContext = GetBindingForProperty(boundType, boundPropertyName, element); if (bindingContext != null) return bindingContext; } return null; }

I thought maybe it would look less horrendous if I used LINQ…

private static ValidationBindingContext GetBindingForPropertyLINQ(Type boundType, string boundPropertyName, 
FrameworkElement root) { foreach (FrameworkElement element in LogicalTreeHelper.GetChildren(root).OfType<FrameworkElement>()) { var result = from FieldInfo field in element.GetType().GetFields(BindingFlags.Public | BindingFlags.GetProperty |
BindingFlags.Static | BindingFlags.FlattenHierarchy) where field.FieldType == typeof(DependencyProperty) let dp = (DependencyProperty)field.GetValue(null) where BindingOperations.IsDataBound(element, dp) let bindingExpression = BindingOperations.GetBindingExpression(element, dp) where boundType == bindingExpression.DataItem.GetType() where boundPropertyName == bindingExpression.ParentBinding.Path.Path select new ValidationBindingContext(bindingExpression, element as UIElement); if (result.FirstOrDefault() != null) return result.FirstOrDefault(); else { // Not found so check all child elements ValidationBindingContext bindingContext = GetBindingForProperty(boundType, boundPropertyName, element); if (bindingContext != null) return bindingContext; } } return null; }

But no – it was still going to suck, the performance would be horrible and the whole thing just looks so… “kludgy”. So, resigned I look on the net – horrified to find that the reflection method was one of two ways developers had commonly resorted to. The other method is to make use of the MarkupWriter class – which to me looked even worse .

It works…

Discovering WPF Bindings

…but does someone know a better way?

Handling Images with the HtmlToXamlConverter

I was asked via a comment “why won’t HtmlToXamlConverter display images, for example those embedded in an RSS feed’s contents?”.

The answer is probably indicated by the comment in the HtmlToXamlConverter classes AddBlock() method :

        case "img":
// TODO: Add image processing
            AddImage(xamlParentElement, htmlElement, inheritedProperties, stylesheet, sourceContext);
break;

And the equally terse AddImage() method itself:

        private static void AddImage(XmlElement xamlParentElement, XmlElement htmlElement, 
Hashtable inheritedProperties, CssStylesheet stylesheet,
List<XmlElement> sourceContext) { // Implement images }

I’d tweaked the HtmlFromXamlConverter AddImage class as follows:

        private static void AddImage(XmlElement xamlParentElement, 
XmlElement htmlElement,
Hashtable inheritedProperties,
CssStylesheet stylesheet,
List<XmlElement> sourceContext) { // Implement images (HACK by Nigel Spencer) bool inLine = (xamlParentElement.Name == HtmlToXamlConverter.Xaml_Paragraph); XmlElement xamlUIContainerElement = null; if (inLine) xamlUIContainerElement = xamlParentElement.OwnerDocument.CreateElement(
null, "InlineUIContainer", _xamlNamespace); else xamlUIContainerElement = xamlParentElement.OwnerDocument.CreateElement(
null, "BlockUIContainer", _xamlNamespace); XmlElement xamlImageElement = xamlParentElement.OwnerDocument.CreateElement(
null, "Image", _xamlNamespace); xamlImageElement.SetAttribute("Source", htmlElement.GetAttribute("src")); xamlImageElement.SetAttribute("Stretch", "None"); xamlUIContainerElement.AppendChild(xamlImageElement); xamlParentElement.AppendChild(xamlUIContainerElement); }

Don’t expect too much from this though. If you really need to display rich HTML in a WPF app then use a Frame control. However, if like me, you’ve got some predominantly textual data stored in HTML and you want to make use of the great FlowDocument reader controls then the HtmlFromXamlConverter is a great little utility.

The source code for my test WPF harness was as  follows:

    public partial class Window1 : Window
    {
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
FlowDocument flowDocument = new FlowDocument();
string xaml = HtmlToXamlConverter.ConvertHtmlToXaml(textBox1.Text, false);
using (MemoryStream stream = new MemoryStream((new ASCIIEncoding()).GetBytes(xaml)))
{
TextRange text = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);
text.Load(stream, DataFormats.Xaml);
}
flowDocumentReader1.Document = flowDocument;
}
}

Some very simple HTML to test. I also tested with HTML source from a  blog post of two and it seemed OK.

<HTML>
<BODY>
<p>The <b>Markup</b> that is to be converted.</p>
<p>An inline image [<img src="http://www.microsoft.com/australia/remix08/images/bling/iamgoing_08.jpg"/>]</p>
<p>Ooh! <i>Beautiful.</i></p>
<img src="http://images.quickblogcast.com/public/visitorImages/black_createdby.gif"/>
<p>Hmm...</p>
</BODY>
</HTML>

ReMIX08 in Australia

Well I’ve booked my flight, registered and got the day off work (in that order). I am not a “web guy”. I’ll go on record as stating that I was over JavaScript and HTML back in 2000. Whilst it was kinda fun to play with for a couple of months I’m not about to go writing any serious applications with those technologies. [I’ll leave that to the hordes of happy web devs who somehow seem to enjoy it.]

Regardless I was very impressed with the content that I saw coming out of Mix08 this year. In particular being such a WPF fan I think Silverlight 2 is sounding pretty sweet. Maybe, just maybe, I’ll convert from writing enterprise client-apps and do some web front-end development? As long as you promise I don’t have to touch a scripting language or HTML right?

I'm going to REMIX. Are you?

So who else is going to ReMIX08? Anyone from Adelaide making the early morning flight over to Melbourne on 22nd May?

Oh – and a complimentary copy of Expression Studio 2 – nice!

Source Code Comments – Time for a revamp

[If you’re impatient then check out the image here to jump straight to the reason behind this post.]

When Microsoft first declared there intent to include support for comments within the C# language I was overjoyed. I was so taken with the idea that I wrote a VB6 add-in that would parse VB6 source comments prefixed by ‘/ and convert them into a HTML page which documents the class. Importantly it also provided a real-time preview window for the current method/property.

As it turned out when .NET was finally released I landed a job coding in VB.NET rather than C#. There were a couple of freeware tools around that would allow the XML documentation files to be produced from VB.NET source code. They were OK but it really wasn’t the same as having the compiler validate comment references. Also most of the tools we tried were a little flaky and prone to crashing every now and then.

Jumping ahead a few years and I’m using C# with Visual Studio 2005 on a large scale project. On this project I was responsible for writing a lot of architecture and doing my best to make sure it was documented. We used NDoc to produce MSDN style Help via MSBuild and our continuous integration engine (CruiseControl.NET). We also had to produce a script that would correctly register the generated v2 Help file to have it integrate seamlessly with the Visual Studio documentation. Setting this up was tricky. It required us to debug and fix the latest NDoc build to properly support generics, use another third party tool to generate the required Help registration goo, write custom NDoc tags for inserting images (like class diagrams) and creating FAQ indexes etc. It would also take about an hour to run (over our 40+ project solution).

But NDoc is dead!

Yes, but as everyone knows Sandcastle lives! The first few drops of Sandcastle were really quite scary. Config files here there and everywhere, write your own scripts to produce the end result. But whilst Microsoft were concentrating hard on getting the fundamental engine right the community came to the rescue  with Sandcastle Help File Builder (SHFB). A full featured, easy to use GUI to produce Help v1, v2 and HTML documentation using the Sandcastle engine. The recent builds of Sandcastle coupled with SHFB and we’re finally back (in fact slightly ahead) of where NDoc left off. The SHFB has even been built to look and feel just like the NDoc GUI – nice!

Sandcastle - UriToThumbnailConverter 

Some HTML v1 output from Sandcastle using SHFB.

Source Comments are ugly

However, having had a chance to write a fair amount of source comments on this particular VS2005 project, one thing became obvious. Improving the quality of the externally viewed documentation (e.g. in dexplore, or HTLP Help Viewer) had a directly negative effect on the readability of the same documentation within the source files (e.g. Visual Studio).

In other words – adding more markup to the source comments made them harder to read in Visual Studio. Yet I want the both of best worlds. I want to be able to produce useful documentation integrated with MSDN but at the same time I want those comments to be easily read by the developer when they are right there in the source.

/// <summary>
/// This <see cref="IValueConverter"/> allows image paths in XAML to be efficiently converted into
/// thumbnail images which could, for example, be used to populate an <see cref="ItemsControl"/>.
/// </summary>
/// <remarks>
/// <para>
/// This converter relies on the image file referenced by the string representation of the value
/// having a thumbnail image stored as part of its metadata. This will be likely for any image that
/// has been taken direct from a modern digital camera. Digital cameras  record a thumbnail image
/// for their own internal processing. This thumbnail "lives" with the metadata, e.g. EXIF tags that
/// record other information such as when the image was taken, the various camera settings etc.
/// </para>
/// <para>
/// If the string representation of the value does not represent a valid file, or the file is not accessible
/// for any reason then a default image will be returned.
/// </para>
/// <note>If this converter is used with a non-string value it will perform a <c>ToString()</c> on
/// the method in order to generate a string which will then be translated to a URI used to
/// load the image.</note>
/// </remarks>
/// <example>
/// The following example shows how the converter can be used in XAML.
/// <code lang="XML" title="Using the UriToThumbnailConverter in XAML" numberLines="true">
/// &lt;converters:UriToThumbnailConverter x:Key="uriToThumbnailConverter"/&gt;
/// ...
/// &lt;Image Source="{Binding Path=FilePath, Converter={StaticResource uriToThumbnailConverter}}" Height="90" /&gt;
/// </code>
/// </example>
public class UriToThumbnailConverter : IValueConverter
{
/// <summary>
/// Converts a string containing an image path (URI) into the thumbnail <see cref="BitmapSource">bitmap</see>
/// image contained within the image.
/// </summary>
/// <param name="value">The value produced by the binding source.</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>
/// A converted value. If the method returns <see langword="null"/>, the valid <see langword="null"/> value is used.
/// </returns>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
BitmapFrame bitmap = BitmapFrame.Create(new Uri(value.ToString()), BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnDemand);
return bitmap.Thumbnail;
}
catch
{
return System.Drawing.SystemIcons.Exclamation.ToBitmap();
}
}

So what’s the solution?

Well – back in those Visual Studio 2005 days I used to use a little tool called CR_Documentor which was written as a DXCore add-in. This provided a real-time preview window of what your source comments would look like once marked-up. This was really useful as there was nothing more annoying that doing a whole bunch of source comments only to find the next day (after the nightly documentation was produced) I had made some silly error with my markup causing corrupt, incomplete or missing documentation. Admittedly the build I was using used to struggle keeping up with some of the really large namespace documentation (e.g. 500+ lines), but it did a good job for the small stuff.

Configuration settings for CR_Documentor.

But please Microsoft, I want more!

What I really want is source comment markup integrated in the Visual Studio editor. When I’m browsing source code I don’t want to see angle brackets and tags all over the place. I want to see clearly readable documentation. When I want to edit the source comments then you can show me the angle brackets. Or better yet – given only a limited set of documentation and standard HTML tags are supported – why should I ever need to see the tags? Give me a limited document editor with a set of extendable “regions” and some basic bold/italic etc. formatting. (Click the image below to see in its full glory what could be a preview of Dev10).

Visual Studio Help Editor

An impression of what source code comment viewing could be like in Visual Studio.

So everyone knows that fixed-width fonts are out, and more readable proportional fonts are in. So why can’t we also get some WYSIWYG capabilities in the editor?

Some features of the new inline WYSIWYG source comment editor:

  1. Comments can be collapsed completely, or to a single line (as per existing region style collapse) using the expand collapse arrow to the left of the class/member. (Not sure how the arrow does a three state collapse – but hey why not?)
  2. Comment sections can each be collapsed to the heading as per MSDN comments.
  3. Default collapse settings for comments are configurable via Visual Studio settings.
  4. It should look nicer than my hacked “Frankenstein” screenshot which is more or less just overlaying the Sandcastle output over a Visual Studio editing window. In particular the comments should be de-emphasized.
  5. Hmm… what else?

Resources:

Sandcastle – Microsoft’s source code documentation engine

Sandcastle Help File Builder – NDoc-like GUI for Sandcastle

GhostDoc – does a “spooky” job of commenting your code for you.

CR_Documentor – real-time preview window of source comments marked up

XML Documentation Comments Guide – explains the various comment tags for VS 2003, 2005, NDoc and Sandcastle

Is Blend a better WPF designer for developers than Visual Studio?

For ages now I’ve had some XAML that consistently generates error messages in the Visual Studio designer. I’ve found this most frustrating because I was never sure quite what was wrong with the XAML. Compiling and running the application and it worked exactly how it was intended. But the designer simply refused to display it – instead giving this standard message.

Cider Invalid XAML Message 

In the Error List I find:

Cider Invalid XAML Error

Huh? Sure indexes “Must be non-negative and less than the size of the collection.” that makes sense. But which index? Line ‘1’ Position ‘616’ simply refers to the DataTemplate definition – but the whole template is considered “in error”.

The application runs and renders perfectly. It only happens with DataTemplates and I get squiggly lines on the entire DataTemplate so tracking down the exact cause is difficult. Something to do with data-binding is about as close as I got before deciding that I could live without the preview (since I don’t actually use the designer for editing).

So last night – inspired by some of the latest Mix08 videos up on WindowsClient.NET I decided to download and try the latest Expression Blend 2.5 Preview. This last time I used Blend was a pre release 1.0 Beta – and I have to say this program has come a long way since then. My initial impression on the v2.5 Preview are very positive. It’s got a whole heap of features that I wish the Visual Studio designer included:

  1. Resource Viewer!
  2. Binding Editor
  3. Better XAML validation

Better XAML Validation? Yep – take for instance problem I was having with my DataTemplates. Loading this UserControl into Blend I was disappointed to find that it also didn’t render. But lo-and-behold it included errors messages indicating its dislike of my method of binding. Must nicer than the “Index was out of range” error reported by Visual Studio for the same control XAML. Instead for each Binding in the DataTemplate I got the following error:

“The property “Path” is set multiple times.”

Ok – so still not great – but at least it had identified each line within the template that it didn’t like and let me know it was something to do with the data-binding. Now as it turns out I had coded the Bindings as:

<TextBlock Text="{Binding TemplateBinding, Path=Name}" .../>

Why am I using TemplateBinding within a DataTemplate? I dunno – seemed to make sense when I did it and given that it ran without complaint the first time I never blinked an eye – just kept on doing it. So taking out the TemplateBinding my Binding is just…

<TextBlock Text="{Binding Path=Name}" .../>

and hey-presto Blend renders my UserControl without a glitch. Beautiful!

Thinking that at last I had solved the mystery of my missing XAML previews in Cider I flicked back to Visual Studio sharing the same project and re-opened the UserControl. Nope – same error. Recompiled the project – nope same error. Bummer . So its something that doesn’t generate errors at run-time, is not a problem with Blend, but which causes the Visual Studio designer to barf?

So ignoring issues around availability/pricing should developers be using Blend in preference to Visual Studio for authoring XAML? Or is Dev10 going to address the shortfall of Cider vs. Blend. I can understand that Blend is geared for UX designers and as such the two products have different end-users in mind but surely Resources and Binding is something a developer needs to be able to manage effectively?

Great Content Abounds

Haven’t posted for a while – I’ve been absorbing the flurry of good content that been blogged recently. Some of my favourites.

Prism

  • RI drops every couple of weeks – its interesting watching the bits take shape. I wish they’d include source comments though. I’m guessing they think its less cluttered without the comments but I find it tedious drilling down into every class/interface/member to try and work out its use. Maybe I’m not familiar enough with some of the pattern implementations – but surely if “learnability” is as higher on the priority list as suggested…
  • I wonder if they strip the comments out when the drop a release or whether they really have no source comments at all?
  • The latest drop shows the teams current thoughts on implementing a Command pattern using a customised ICommand implementation.
  • I really like the Region Manager stuff, using an attached property to allow any Panel or ItemsControl to become a region with a single XAML attribute.
  • I also found Ward Bell’s post on “Prism Camp” describing the working party that was put together to help kick off the project quite fascinating. [Side note to self: Ward is the product manager for DevForce.NET – interesting.]

Unity

  • Having some fun playing with Inversion of Control (IoC) in my test app. Whilst its got some great advantages its interesting to consider at what point that added complexity outweighs the gains – e.g. at what size/complexity of app does it become worthwhile. (Note the documentation does contain guidance on that question).
  • I first looked at this via its use in the earlier Prism drops but I notice that its just been officially released.

Josh Smith’s WPF Bootcamp Video

  • Where he walks through his demo X-tray WPF app. Definitely worth checking out if you’re interested in MVP/MVC etc. implementations for WPF. Great stuff.

Karl Schifflet’s next WPF Business Application instalment

Rob Relyea

  • This guy is blogging links to some great content (including most of the above) almost as fast as I can consume it!

Updated RibbonBar

Update to RibbonBar – is now a separate Resource file. Simply merge into the resource dictionary and use the RibbonBarStyle on the TabControl you want to look like a Ribbon. The sample below can be copied direct into XAML viewer (e.g. Kaxaml). This is a XAML only version so doesn’t contain any of the command binding stuff, curvy tab headers etc.

<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="http://www.spencen.com/downloads/RibbonBarResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<StackPanel>
<TabControl Style="{StaticResource RibbonBarStyle}">
<TabItem Header="Tab 1">
<ToolBarTray>
<ToolBar>
<Button Tag="http://www.spencen.com/downloads/Button1_48.png">Button 1</Button>
<Button Tag="http://www.spencen.com/downloads/Button1_24.png">Button 2</Button>
<Button Tag="http://www.spencen.com/downloads/Button1_24.png">Button 2.1</Button>
</ToolBar>
</ToolBarTray>
</TabItem>
<TabItem Header="Tab 2">
<ToolBarTray>
<ToolBar>
<Button>Button 3</Button>
<Button>Button 4</Button>
<ComboBox Text="ComboBox 1" Width="80"/>
</ToolBar>
</ToolBarTray>
</TabItem>
</TabControl>
</StackPanel>
</Page>

Grab the RibonBarResource.xaml from here.

Revisiting Commands

Having put together the basics of the user interface for my current project I decided to do some more reading regarding the best practices around using a Command Pattern in WPF.

Specifically this means determining how to use the ICommand and RoutedCommand. My previous attempt (without reading any of the documentation) was something of a failure but I pretty much have the same goals in mind:

  1. UI elements that perform an action that is not purely UI related are required to be bound to a Command. This must be easily done in XAML.
  2. The Window/Page itself should have minimal (i.e. as close to possible to zero) code in the code behind. This means no ugly event handlers.
  3. The Command or more likely the Command Binding mechanism will be responsible for setting attributes on the associated UI element(s). So this includes things like Text, Image, Tooltip, Enabled, Visible etc.

The closest thing I’ve found so far in terms of recommended approaches is the collection of blog entries written by Dan Crevier back in 2006. Dan does a great job of discussing a simplified version of the Data Model – View – View Model (DV-V-VM) that the team working on Microsoft Max used. Having said that there are some approaches that he takes that I either find too unwieldy (one command per class) or (just as likely) don’t fully comprehend.

Reading straight out of the MSDN documentation I stared with:

    <Page.CommandBindings>
        <CommandBinding Command="{x:Static pages:RibbonTest.WriteEntryCommand}" 
Executed
="CommandBinding_Executed"
CanExecute
="CommandBinding_CanExecute"/>
</Page.CommandBindings>
...
<Button Command="pages:RibbonTest.WriteEntryCommand"/>

This involved defining my own RoutedCommand on the page itself (pages:RibbonTest) and then binding the Executed and CanExecute events to event handlers on the page. Of course this doesn’t meet any of my three requirements, – it’s too much XAML, it requires code behind event handlers and with the exception of the Enabled property doesn’t “reflect” command properties to the UI element.

Needless to say I went through a whole raft of possible solutions from here (refer to references below), trying each in turn to see what worked for me and what didn’t.

At the moment I have created an attached dependency property (as per Dan’s post) so that my XAML is nice and concise.

<TabControl Name="tabControl2" Style="{StaticResource RibbonBarStyle}">
    <TabItem Header="Holidays">
        <ToolBarTray>
            <ToolBar Header="Select a Holiday">
                <Button commands:CommandBinder.Command="{Binding Controller.NewHoliday}"/>
                <Button commands:CommandBinder.Command="{Binding Controller.OpenHoliday}"/>
</ToolBar>
        </ToolBarTray>
    </TabItem>
...


</TabControl>

The Controller referenced above is instantiated by the form and defines all of the commands available for the form. It is also responsible for keeping the form state which is then reflected in the commands, and thus by the buttons. The commands are actually a custom class (UICommand) that is a “wrapper” around a RoutedCommand and contains other metadata that is associated with the command. This includes the caption text, full description, image, IsEnabled and IsAvailable (visible/security). The wrapped RoutedCommand also defines any keyboard gestures.

Taking this approach means that:

  1. Only the attached property needs to be set – the CommandBindings are not required – this is done automatically by the attached property.
  2. The command execution logic (callback) lives either in the controller, or in a UICommand derivative (for common functions like navigation).
  3. The only code required in the form code-behind is the instantiation of the controller. Of course this could easily be done in XAML too if preferred.
  4. In addition to setting the Text (via binding), Enabled and Visibility properties I’m also using the CommandBinder to build a groovy Tooltip complete with input key shortcuts.

XAML Ribbon with Tooltip

Of course its not all roses – there are more than a couple of “nasty” bits in my implementation at the moment. One surprising one was an oddity in the ICommandSource interface. Within the CommandBinder attached property I thought to use this interface to set the Command property on the source at the same time as I registered the RoutedCommand. However, it turns out that the ICommandSource.Command property is read-only – most frustrating.

More than anything though I’m curious as to how everyone else tackles implementing a command pattern (and MVC/MVP etc.) in WPF?

References:

WPF Commands on Code Project

Karl on WPF

Rob Relyea on ICommand, RoutedCommand and RoutedUICommand

Josh Smith on RoutedCommand

Josh Smith on MVC

Commands in Prism (some great comments)