Dutton's blog

Using data bound properties in the WPF ValidationRule

I recently needed to use to make sure that a number entered into a text box was less than the value of a property on my view model.

Arguably, this sort of business logic might be better off inside my view model; possibly let the property get set regardless, then verify and do something with IDataErrorInfo to notify the GUI if it's wrong before updating my model data if required. But in this case I am binding straight onto a property which is held inside a class I cannot modify, so I decided to try and use WPF's built-in binding validation mechanism.

So far so good; off I went deriving from ValidationRule and overriding Validate, but I soon came a cropper trying to access the view model. The problem is that ValidationRule isn't a DependencyObject so I can't add a dependency property to bind my view model to, and the specifics of my usage (this TextBox is dynamically generated in a DataGrid in code, but that's for another blog post), meant that the solution suggested here didn't help me, the binding fails at the point the TextBox is created so never gets updated when it's finally set.

So after a bit of a dig about in the MSDN I found that if you set

ValidationStop = ValidationStep.UpdatedValue

on the ValidationRule the value parameter in the Validate method is the BindingExpression itself, from which you can query DataItem to get the binding source object that the expression uses (which in my case is my view model).

Great stuff, but now how do I get my actual value from the BindingExpression? I can't use SourceValue, or SourceItem, because even though under the debugger they show my value, they are both internal.

So along comes .Net 4.5 to the rescue with a new ResolvedSource property for BindingExpression which will return the binding source object, in this case the TextBox text property which means I can do something like this:

public class NumberIsGreaterThanVmValidationRule : ValidationRule
{
  public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
  {
    var result = new ValidationResult(true, null);


      
How to fix: "The command you are attempting cannot be completed because the file 'xxx.vdproj' is under source control and is not checked out" when building solutions containing setup projects in VS2010

Today I revisited some old projects under Visual Studio 2010 to carry out some maintenance. The solution file contains a handful of C# code projects, and two Deployment Projects (vdproj). Every time I tried to build, it would succeed but I would be prompted with this dialog for each Deployment Project.

VS2010 vdproj checked in

Clicking OK or closing the dialog would prompt another to pop-up, at least a dozen or so times before finally finishing the build.

A bit of digging about (some of the links provided in various forums posts have since become broken) and Microsoft released a hot fix back in April 2011 which you can find here. According to one post, the issue is down to a different hashing algorithm employed by Microsoft for generating GUIDs in SP1 of VS2010.

Any deployment projects created before SP1 and checked into source control will then attempt to update the component GUID and popup this error, although I seem to get this on every build if the .vdproj is checked in, regardless of whether VS2010 SP1 has previously updated the file.

Fortunately installing this hot fix makes the problem go away and stops me having to mash my enter key every time I want to build.

Playing with Predicate

I came across a problem during recent round of refactoring. Here's a contrived simiIar example.

I have an IEnumerable, MyThings contains a property of type Enum called MyThingType. Scattered around my class I found I had quite a bit of duplicated code consisting of a Linq Where statement to filter the IEnumerable based on a specific values of MyThingType and then perform some additional actions on the result.

var filtereredThings = MyThingsList.Where(t => t.MyThingType == ThingType.ThingA);
// other stuff on filteredThings

All good so far, I extracted the common code into a new private method call which returned my result and took the MyThingType as a parameter to filter on, the problem arose when my last Where statement filtered on two MyThingType values.

private IEnumerable FilterAndProcessThingType(IEnumerable data, ThingType filterType)
{
  var filtereredThings = MyThingsList.Where(t => t.MyThingType == filterType);
  // other stuff on filteredThings and return result
}

I changed my method to take a params parameter for the filter so I can pass a variable number of MyThingType in, but how do I change my Linq?

private IEnumerable FilterAndProcessThingType(IEnumerable data, params ThingType[] filterType)
{
  var filtereredThings = MyThingsList.Where(t => t.MyThingType == ???);
  // other stuff on filteredThings and return result
}

This is where Predicate comes in; a Predicate is a function which returns true or false. This means I can dynamically create one to do my MyThingType check and put it in my Where's Lambda expression.

private IEnumerable FilterAndProcessThingType(IEnumerable data, params ThingType[] typeFilter)
{
  var thingTypeMatcher = new Predicate<tuple<thingtype, thingtype[]="">>(t =>
  {
    var thingType = t.Item1;
    var thingTypeArray = t.Item2;
    return thingTypeArray.Aggregate(false,(current, type) => current | thingType == type);
  });
  var filtereredThings = MyThingsList.Where(t => thingTypeMatcher(new Tuple<thingtype, thingtype[]="">(t.MyThingType, typeFilter));
  // other stuff on filteredThings and return result
}

And that's it, now I can pass a variable number of types to match into my common code.

How to fix: "The Windows Phone Emulator wasn't able to create the virtual machine: Generic failure" under VMWare Fusion 4.1.4

I use an iMac at home, so any Windows development is done in a Windows 8 virtual machine running under VMWare Fusion 4.1.4.

I ran into a problem this evening when playing around with some Windows Phone 8 development and thought I'd share the solution. It turns out the default Fusion configuration doesn't support the hardware assisted visualization (Hyper-V) that the Windows Phone SDK Phone Simulator uses.

Not to worry, just do the following (works for me under 4.1.4).

    • Shutdown the virtual machine.
    • From the Virtual Machine Library Ctrl-Click on the virtual machine's icon and select Show in finder.
    • Ctrl-click on the vm's bundle under Finder and click Show Package Contents.
    • In there you will find a .vmx file, this is the virtual machine's configuration file. Open this in your favorite editor.
    • Add the following two lines to the end of the file:

vhv.enable = "TRUE"
hypervisor.cpuid.v0 = "FALSE"

  • Save the file, restart your VM and the Phone Simulator will work fine.

NB: My VM has two processors, I haven't tried this on a single process VM yet.

How to fix: "Unable to Activate Windows Store App. The activation request failed with error..."

Those of you who know me will know that I'm a bit of an Apple fan-boy, so anything running Windows natively has over the years experienced a rather unceremonious departure from my tech collection.

That does make my current pet project of playing around with Windows 8 App Store development slightly tricky, so I've turned to virtualising Windows 8 under VMWare Fusion to get my out of work C# fix. This generally works well, except I seem to regularly run into this error when I first run my app.

Unable-to-activate-Windows-Store-app-Issue-with-its-license

I think it may be something to do with the way I regularly suspend and resume (instead of shutting down) my VM in between work stints causing some problems with the built-in development licensing that Microsoft now uses.

I've read online that some people have had success just performing a "Clean" and then "Build" in VS2012, but that doesn't seem to work for me, instead I have to close the solution and delete my project's bin and obj folders.

Hope this helps someone.