Thoughts on Mesh Remote Desktop

One of the features of Microsoft’s Mesh is to provide a remote desktop connection to any of your devices via the Live Desktop. That amounts to being able to remote desktop from any of the supported browsers. Microsoft’s Windows Home Server already provides me with this experience and whilst I can’t say I’ve used it a lot – it has helped me out a few times in a big way.

I had assumed that the technology involved in the Window Home Server remote desktop via the browser was the same technology that would be powering Window Live Mesh. Whether it is or not I can’t tell – but the user experience is certainly different.

When you connect to Live Mesh it starts a remote desktop session in a window – complete with the standard “Mesh” sidebar window “clipped” onto the right hand edge. What’s odd though is that the remote desktop uses the resolution of the remote hardware and is scaled to fit in the window – and the scaling does not preserve the aspect ratio. So in my scenario – lets say I connect to my home desktop via my Fujitsu Lifebook. That means I’m viewing a 1920×1200 + 1280×1024 multi-monitor desktop on a laptop screen with a resolution of 1024×768. Umm… not very useful – showing a 3200×1200 very wide desktop squished to a 1024×768 display. It has a mode that allows switching between actual and fixed size – but at those resolutions its kinda akin to using remote desktop from a PDA into a PC – peering through a tiny window and endless scrolling.

Live Mesh Remote Desktop - Squished

Another point of difference is that unlike a standard remote desktop connection is that for the Live Mesh to recognize the devices it appears that you have to be signed in on each device. So no chance of using wake-on-LAN to get your machine up and running and ready to connect. You’d also have to have it auto-logon – hmm… suitable for my Media Center PC maybe – but not something I’d want on my other devices.

In fact the more I play with this, the more I begin to think its not really remote desktop as we know it. For starters the remote machine stays active – i.e. mouse moves and everything you’re doing on the remote desktop can be seen on the remote machine – unless you click the “Hide desktop on remote device” button.

Secondly, its so much slower than a standard remote desktop. Even using it on a LAN its painfully slow to render the desktop background – yep that’s right its rendering everything using bitmaps – and there doesn’t seem to be any configuration options?

Thirdly, because it really just seems to be screen scraping the remote device (as opposed to actually logging in and creating a new virtual session) it means you get all kinds of weird behaviours. For example, when I remote connect to the laptop the logon screen shows the Fingerprint reader user interface. Umm… not really much point ’cause the hardware I’m connected with doesn’t have a fingerprint reader.

Early days though – hopefully the feedback being logged up on Connect will help shape the product.

Live Mesh Connect

I’m still waiting on an invite to the developer Tech Preview to see what the Live Mesh APIs look like.

P.S. The folder sharing Live Mesh stuff seems to be working very nicely. I already prefer it to FolderShare.

Windows Live Mesh Invite

Woohoo – just got an invite to Window Live Mesh – am installing on a few machines now.

As an aside: I’ve been an intermittent user of FolderShare since before it was acquired by Microsoft. Will be interesting to see how they plan to merge FolderShare, Skydrive and Live Mesh going forwards.

BindingGroup in .NET 3.5 SP1?

Of all the new features trumpeted for .NET 3.5 SP1 recently the one bullet point that really caught my attention was this little gem (from Brad Adams blog).



A new BindingGroup in System.Windows.Data (additional databinding support)


At this stage I haven’t downloaded and installed the bits. Anyone know what this “BindingGroup” refers to – I haven’t heard/seen it mentioned anywhere else.


[Update 28-May-2008:The WPF Performance blog provides some further hints on the purpose of BindingGroup]

Item-Level Validation – By using Binding Groups this applies validation rules to an entire bound item. For example it can enable validate & commit scenario for a form with few bind-able edit fields. (available in final RTM bits only)

Applying MetaData to WPF Bindings

This post describes how I’m applying MetaData defined in my model to WPF controls at runtime. The goal is to keep the XAML concise without cluttering it with property settings that obscure the form layout intent and ensuring it stays in sync with the model across all forms in the application. Refer to Karl Schifflet’s recent passionate post about why MetaData is important.

In WinForms I’ve traditionally used the data Binding to identify how MetaData should map to controls. So the following describes my attempt at the same thing in WPF.

I’m using attributes to define MetaData directly against my model classes. I’d like for it to be more open than that – for instance extracting the MetaData from a database, config file etc. – but attributes is a good place to start. Here’s an example property from my Holiday model class.

    [Mandatory]
[Annotation("Name", "Name of this holiday")]
[StringData(MaximumLength=50, Case=CharacterCasing.Upper)]
public string Name
{
get { return _name; }
set
{
if (!Object.Equals(_name, value))
{
_name = value;
OnPropertyChanged("Name");
}
}
}

So in this example I’m using three custom attributes. [Mandatory] is pretty self explanatory. Whilst its not used by the MetaData Applicator it is used by the ValidationEngine to create a MandatoryRule.

The [Annotation] attribute derives from System.ComponentModel.DisplayName and extends it by including extended descriptions for tooltips and possible help keys etc.

The third [StringData] attribute is the one that defines the MetaData specific to string data types. The attributes themselves are defined in a neutral namespace and assembly (Spencen.MetaData) with no references to any presentation assemblies.

Taking a look at the StringDataAttribute class its just a bunch of properties with no inherent behaviour (like most attributes).

    [MetaData]
public class StringDataAttribute : StringLengthAttribute 
    {
public StringDataAttribute() : base()
{
}
        #region Public Properties
public string Format { get; set; }
public Type DataType { get; set; }
public CharacterCasing Case { get; set; }
public bool MultiLine { get; set; }
public bool AllowTab { get; set; }
public bool AllowNewline { get; set; }
        #endregion
    }

The StringDataAttribute class is itself decorated with a [MetaData] attribute. This tells the MetaData Applicator that it needs to be considered when applying MetaData properties to the UI. [The StringLengthAttribute that this class derives from is actually another ValidationRule attribute that results in the creation of the StringLengthValidationRule.]

Now the tricky part in all of this was trying to “hook” into the WPF Binding pipeline. I tried all the likely approaches – inheriting from Binding, looking at BindingExpression and eventually creating a custom MarkupExtension that offloads most of the work to the standard Binding MarkupExtension.

Once I got that far I looked around and found that the MarkupExtension appears to be the current approach. Mine is currently a very simplified implementation – as I later found out there are much better examples around including this one or the one used by the Enterprise Library Contrib’s Standalone Validation Block.

Having a customised Binding gives several advantages not the least of which is applying default values for the Binding itself. Ever got tired of adding ValidatesOnDataErrors=true, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged to every Binding!?

Anyhow – more on that later – for now I use the following code within the ProvideValue() method of my custom MarkupExtension.

    IProvideValueTarget valueTarget = (IProvideValueTarget)serviceProvider.GetService(
typeof(IProvideValueTarget)); DependencyObject dependencyObject = valueTarget.TargetObject as DependencyObject; DependencyProperty dependencyProperty = valueTarget.TargetProperty as DependencyProperty; if (dependencyObject != null && dependencyProperty != null) { if (dependencyObject is FrameworkElement) { object dataContext = ((FrameworkElement) dependencyObject).GetValue(
FrameworkElement.DataContextProperty); if (Applicator != null) { PropertyDescriptor property = TypeDescriptor.GetProperties(dataContext).Find(_path, false); if (property != null) { foreach (Attribute propertyAttribute in property.Attributes) { // Check if the attribute class is itself decorated with a MetaData attribute. if (TypeDescriptor.GetAttributes(propertyAttribute).Contains(new MetaDataAttribute())) { Applicator.ApplyTo(propertyAttribute, dependencyObject, dependencyProperty); } } } } } }

Essentially its just checking each Binding and then looking for [MetaData] decorated attributes on the data source. [Note that this code overly simplifies resolving the DataContext and Path. Remember the path is just that not necessarily just a property name, it can even have things like indexers etc. in it.]. Once its found an attribute it calls out to the statically assigned Applicator.

The Applicator simply consists of a registered list of types and IMetaDataApplicators. Prior to any custom data Binding the application registered those [MetaData] attributes that it wishes to apply to the UI with the Applicator on the markup extension. Like so…

    MetaDataExtension.Applicator = new MetaDataApplicator();
MetaDataExtension.Applicator.RegisteredApplicators.Add(
typeof(StringDataAttribute), new StringDataApplicator());

The StringDataApplicator class then does whatever it desires with the StringDataAttribute, target object and property that its been given. Here’s a simple partially complete example:

    public class StringDataApplicator : IMetaDataApplicator
    {
public void ApplyTo(Attribute attribute, object targetObject, object targetProperty)
{
StringDataAttribute stringData = attribute as StringDataAttribute;
if (stringData == null) 
throw new InvalidOperationException("StringDataApplication only supports StringDataAttribute."); TextBoxBase textBoxBase = targetObject as TextBoxBase; if (textBoxBase != null) { textBoxBase.AcceptsTab = stringData.AllowTab; textBoxBase.AcceptsReturn = stringData.AllowNewline;
} TextBox textBox = targetObject as TextBox; if (textBox != null) { switch(stringData.Case) { case Spencen.MetaData.CharacterCasing.Lower: textBox.CharacterCasing = System.Windows.Controls.CharacterCasing.Lower; break; case Spencen.MetaData.CharacterCasing.Upper: textBox.CharacterCasing = System.Windows.Controls.CharacterCasing.Upper; break; case Spencen.MetaData.CharacterCasing.Camel: // TODO: Put hooks in to do formatting. break; case Spencen.MetaData.CharacterCasing.Title: // TODO: Put hooks in to do formatting. break; } textBox.MaxLength = stringData.MaximumLength; } } }

The XAML to bind the Holiday classes Name property using the MetaData MarkupExtension would be:

    <TextBox Grid.Column="1" Grid.Row="0" Width="150" Text="{meta:MetaData Name}"/>

The rendered TextBox would use the Binding properties defined as the default on the MetaData MarkupExtension (as opposed to the standard Binding class defaults). It will have its MaxLength set to 10 and entry forced to uppercase characters. Of course there are plenty of other properties on the StringDataAttribute that could have been used. For example:

  • Defining a DataType that specifies a type that is used as an IValueConverter and/or formatter. This can be used to setup all the necessary plumbing for allowing data entry of specific string types – such as phone numbers, e-mail addresses etc.
  • Using MaximumLength to determine the optimum length for a TextBox. Again this helps with consistency – all 4 character code fields are automatically set to the standard width for a four character field.
  • Using the AnnotationAttribute to set the Tooltip.

MetaData

Asynchronous Validation

Occasionally I’ve wanted to execute Validation Rules that take a significant duration to execute (anything more than half a second for example). Normally these involve some cross-tier communication, e.g. database access, web service call etc.  Examples of these types of validation include:

  1. Validating that a field is unique – for example when entering a new Inventory Item which requires a unique code. This could also require a unique combination of field values, for example an item name that must be unique during its effective lifetime specified by a from/to date.
  2. Validating stock levels for a selected product.

It could be argued that these types of validation are best performed by the business layer on the application server after the user has committed the transaction, i.e. pressed the Save/Submit button. Of course the rules must be validated at that point anyway – since the business layer on your application server should never trust any data being sent to it. But that doesn’t stop us using the same rules to provide timely warnings to the user prior them submitting a form full of data.

The following code shows an sample ValidationRule designed to execute asynchronously.

/// <summary>
/// Sample validation rule that executes asynchronously by default.
/// </summary>
public class SampleAsyncRule : ValidationRule
{
private int _milliSecondsToDelay;
public SampleAsyncRule(int milliSecondsToDelay)
{
_milliSecondsToDelay = milliSecondsToDelay;
IsAsync = true; // Setting IsAsync to true ensures the Validate method is executed on a background thread.
    }
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
// This call could be replaced with a cal to the application service tier via a web service, remoting etc.
        System.Threading.Thread.Sleep(_milliSecondsToDelay);
Random random = new Random();
if (random.Next(100) < 50)
{
return new ValidationResult(ContentSeverity.Error, "Async validation has determined an error.");
}
else
        {
return ValidationResult.ValidResult;
}
}
}

When validating a registered rule the FormValidator checks the ValidationRule.IsAsync flag. If set to true it executes the Validate method on the rule using an asynchronous delegate call. The rule is interpreted as having returned a “pending” ValidationResult which will put the Validator in an indeterminate state (assuming it was previously in a Valid state). When the async delegate completes a callback method on the Validator is fired which extracts the real ValidationResult and removes the temporary “pending” result.

protected override void ValidateInternal(object validationSource)
{
OnValidating(EventArgs.Empty);
foreach (Spencen.Validation.Rules.ValidationRule rule in RegisteredRules[validationSource])
{
Spencen.Validation.ValidationResult result;
if (rule.IsAsync)
{
AsyncValidateCaller caller = new AsyncValidateCaller(rule.BeginValidate);
IAsyncResult asyncResult = caller.BeginInvoke(validationSource, 
CultureInfo.CurrentCulture,
ValidateCallback, caller); result = new AsyncValidationResult(asyncResult); } else { result = rule.Validate(validationSource, CultureInfo.CurrentCulture); } ExtractErrors(result); } OnValidated(EventArgs.Empty); }

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?