What an Awesome Day!

Today was a great day for me.

It didn’t start off to well. I overslept, missed breakfast with my son, and only just got to work on time.

Things picked up a little from there – I’ve been working on some seriously cool custom grid rendering at work for a prototype app. Basically bending the standard WinForms DataGridView to do row grouping with headers and calculated footers, expand, collapse, switching between single line and multi-line preview etc. So an hour or so of coding bliss…

Around midday I was giving a talk on Windows Vista as part of a series of “lunchbox” education sessions I’ve been trying to get off the ground at work. I’d spent a good portion of previous night setting up my machine with demos. However, when I went to set up my machine at work I realised that my machine has only two DVI outputs and there I am stuck with no DVI to analog connectors – so I can’t connect it to the projector. Ended up doing an “off-the-cuff” presentation using a Vista Business machine – but via remote desktop so no Aero Glass . I think I pulled it off but was a little disappointed.

I get some really good news later in the afternoon – more than makes up for any of the days minor inconveniences. At this point the day is already a Very Good Day.

Tonight I left early (before 6pm) so I could take my son and daughter swimming. Before we leave for the pool I set the latest dotnetrocks show to download. The kids have a great time at swimming – which by proxy means so do I. Now its a Great Day.

On the way home I remember that today is the 30th October and why that’s important. I bundle the kids out the car and we listen to the first 10 minutes of episode 285 of dotnetrocks. Now I’m not sure how much pre-schoolers get out of listening to dotnetrocks normally – but even they get excited when they hear my name read out as one of the two winners of a 24″ LCD monitor! Or maybe they just got excited because I was jumping up and down and shouting?

Day status – Awesome!

Dell UltraSharp 2407WFP Font Dell UltraSharp 2407WFP Back   

Big thanks to Microsoft Europe for the prize and Carl and Richard for an awesome show. I wonder what I’ll get in the mail first – the Brain Bag or the monitor?

More Thoughts on Validation

I’ve been thinking a little more about what I want out of a Validation Engine – here are some more random thoughts…

Validation Scopes

  1. Business Rules. These are defined within the application model – normally within the classes used to represent the business objects. Examples include – date of birth that must be historic, cheque number must be unique, expiry date must be greater than start date.
  2. Form Rules. These are defined within the form definition – for WPF applications this could be via XAML. They represent ad-hoc rules that are specific to a form. In some cases this will be adding rules to data represented by business objects (e.g. via data-binding) which may already have a set of Business Rules. In other cases they will be applied to un-bound data. An example of an un-bound form rule is a check-box that must be checked by the user to verify they have read the instructions on the screen before being allowed to proceed.
  3. Data Rules. These are defined by the restrictions that occur because business data is mapped to some underlying data model. Examples include maximum string lengths, numeric precision (entering 4.000000001 might exceed storage capabilities), non-nullable fields.

Validation Timeframe

  1. Synchronous. The validation is immediately performed by the rule yielding either a pass or fail result. Examples of validation that can be synchronous include expiry date being greater than start date.
  2. Asynchronous. The validation cannot be immediately determined by the client and requires some potentially long running component. In this scenario the validation rule may yield a “to be determined” result. This will almost certainly be the case if the validation requires access to data not stored on the client and needs to make a complex query direct to the database – or more likely a fairly simple query that is marshaled to the application logic running on the server – for example via a web service. Examples of validation that can be asynchronous include validating that a cheque number is unique.

Validation Roll-up

  1. Know whether a rule has passed or failed. Note that a rule may affect multiple data elements.
  2. Know whether a data element (i.e. property) is valid. Note that a data element may be affected by multiple rules.
  3. Know whether a data object (i.e. business object instance) is valid. Requires that all its data elements are valid.
  4. Know whether a form is valid. Requires that all its data objects are valid.

Validation Triggers

  1. OnBinding. Validation occurs during binding updates.
  2. Forced. Validation is programmatically forced – either for a single rule, a single business object instance or an entire form.
  3. Suppressed. Each rule may be temporarily suppressed. Alternatively all rules may be suppressed via a single method call.

So far I’ve checked out Paul Stovell’s excellent post on codeproject. Also the post that this spawned by Martin Bennedik which also discusses the Patterns and Practices team’s Validation Application Block (VA. Here’s a list of the VAB meta-data rules.

I’ve also been reading up on IdeaBlade’s DevForce toolset which has a good whitepaper on what they refer to as “verification”.

WinForms Animation

[This post stemmed from a conversation I had today where I was trying to preach the wonders of WPF – particularly in terms of being able to declare simple yet effective animations for UI elements. Contrasting it to what we used to have to do “when I was a lad”…]


A couple of months back when I was working on the WinForms version on my PhotoPlay applet I was trying to do some simple animation using WinForms (GDI+). The effect I was trying to generate was a “fade away”. When a selected photo was removed (via Delete key) it was to fade to transparent and also shrink to nothingness around its centre.


I wanted to use a Timer to make sure that the effect always took a set amount of time, e.g. 500ms. I always use this approach because it makes sure your animations behave nicely no matter how meagre your hardware. The only other obvious approach is to animate every frame – regardless of how long in takes – I’ve never found this too useful.


So with my “fade away” animation coded up in the form I realised that I now how the need for another animation. This time when double-clicking on an image it needed to scale to full size, rotate to zero degrees and position itself in the centre of the window. Hmm… another Timer and custom code perhaps. At the same time I realised my previous “fade away” animation wasn’t working to well when a user tried multiple deletes – deleting one before the previous had fully faded.


Obviously creating a separate Timer instance for every animatable object isn’t going to be very efficient in terms of costly timer resources. Hence the birth of the Transition and TransitionManager classes.


Spencen.Drawing


This class allows simple animations to be performed with very minimal code in a WinForms application. The TransitionManager internally uses a BackgroundWorker to perform the animation – bubbling an event up whenever a transition step occurs so that the UI can redraw. The thing to note with all of this is that it will only work with classes that derive from GraphicsObject. Within PhotoPlay this is the individual photos – but it can be any regular or irregular shaped graphic.


Typically the UI will consist of a number of graphical elements that require GDI+ rendering and hence these could be stored in a “shapes” collection and rendered in OnPaint.

        protected override void OnPaint(PaintEventArgs e)        {            base.OnPaint(e);            foreach (GraphicsObject graphicsObject in shapes)            {                graphicsObject.Paint(e.Graphics);            }        }

To animate these objects its as simple as something like the following (although you may prefer slightly less randomness in your own applications ).

        private void animateButton_Click(object sender, EventArgs e)        {            Random randomizer = new Random();            foreach (GraphicsObject graphicsObject in shapes)            {                Transition transition = new Transition(graphicsObject,                    randomizer.Next(1000) + 200,                    randomizer.Next(360),                    randomizer.Next(5) + 1,                    new PointF(randomizer.Next(400) + 50, randomizer.Next(400) + 50),                    randomizer.Next(50) / 100.0f + 0.5f);                transitionManager.Add(transition);            }            transitionManager.Start();        }        private void transitionManager_TransitionStep(object sender, TransitonStepEventArgs e)        {            // A transition has occurred so force a redraw. Would be better if we added            // Bounds to GraphicsObject so we could do Invalidate(e.Transition.Target.Bounds);            Invalidate();        }

Here’s a ClickOnce online sample and here’s the zipped source code for it.


Windows Forms Transition Manager Screenshot


Roll on WPF and Storyboard double buffer animations


[UPDATE: For those looking for a more fully featured transition/animation library for WinForms I suggest you take a look at Richard’s offering up at http://code.google.com/p/dot-net-transitions. ]

WHS Remote Access

One of the features of Windows Home Server (WHS) that I really like is the ability to use the server as a remote access “hub”. It means I can remote desktop into any one of my home machines from anywhere on the planet. This is kinda cool and can be used to:

  • Fire off disk defrags, backups, video renderings (try rendering an hours worth of HD multi-track video with effects! – even on my own mini render-farm it takes forever).
  • Use WebGuide to setup my TV recording schedule (of course if I allowed external access to WebGuide through HTTP I wouldn’t need WHS for this).
  • Do some coding on VS 2008 Beta 2 via my home workstation to try out some stuff. Handy when I don’t want to install the Beta on my work laptop but need to do a quick proof on concept.

But for this to work it means I need to keep all my computers running 24 hours a day right? Nope – WOL to the rescue – that’s “wake on lan” which has been sitting there on all my BIOS’s for years now but I’ve never used it!

So how does it work – well in picture format it goes something like this:

Login to my WHS box using https://{myUniqueName}.homeserver.com .

Home Tab

From here I can access all my Shared Folder content – kinda neat for uploading images whilst on holiday etc. to make sure they’re all backed up nicely as part of my home-wide backup policy.

Clicking on the Computers Tab shows a list of all the computers configured in my current home setup so far (I haven’t gotten to all of them yet).

Computers Tab

From this we can see that of the three machines only the Media Center PC is currently running (as per the WHS box it also runs 24/7). The WHS box itself isn’t listed below since but we can click on the “Connect to your Home Server” to bring up the WHS dashboard.

Dashboard Backup Tab

The WHS dashboard actually runs as a windowed remote terminal application. This is kinda weird and takes some getting used to – seeing pop windows rendered in the WHS host theme rather than the local theme. The default page shows the backup status for each machine.

Clicking on the Wake On Lan tab gives us the following screen which shows which of the machines are online (switched on and connected to the network) together with their MAC and IP details.

Dashboard WakeOnLan tab

So from here we click on the machine that we wish to start and then click on the “Wake Up” button. At this point we logout of the WHS dashboard and go make a cup of coffee whilst that machine boots up.

Computers Tab 2

After a few minutes we see that the machine is now available for connection. Woohoo! Simply click on the “available” machine and we’re away with a full-screen (optional) remote desktop connection. I don’t get glass – but hey I can live with that

Login

I’ve tried the remote desktop from a few locations and it works surprisingly well even though I’ve only got a standard ADSL connection at home with a very limited 256k upload speed.

This is probably a good time to mention that the Wake On Lan feature does not come out-of-the-box with WHS. Its one of the cool Add-Ins that are floating around on the net – this particular one by Evangelos Hadjichristodoulou. I’ve played with the WHS SDK myself and its pretty cool – certainly very easy to make a simple add-in.

Validation Engine

I’ve now had a chance to play with many (all?) of the Validation classes in WPF under .NET 3.5 and here is a brief summary of my findings thus far.

Binding Contains the ValidationRules property which is a collection of rules that apply to and are triggered by that binding.
Also has properties to apply “standard” validation rules, being ValidatesOnDataErrors and ValidatesOnException.
Setting NotifyOnValidationError=”True” is required in order for the attached Validation.Error event to be raised.
ValidationRule Abstract class that forces derived classes to implement a Validate method. This is pretty straight forward and works well in that it returns a ValidationResult which is easily extendible.
ValidationResult Contains an ErrorContent property defined as object that allows rich validation errors to be returned.
DataErrorValidationRule Allows validation to be performed via the IDataErrorInfo interface on the binding context (assuming it implements it).
Equivalent to setting ValidatesOnDataErrors=”True” on the Binding.
ExceptionValidationRule Converts binding exceptions into validation errors. Can’t see this as being the primary approach to validation – but does provide a useful method for catering for real exceptions.
Equivalent to setting ValidatesOnException=”True” on the Binding.
Validation Static class that provides some important attached properties (Errors, ErrorTemplate and HasError) and an attached event (Error).
ValidationError Represents an error that has been generated by a ValidationRule or manually created via a call to the MarkInvalid method.
It links the Binding, ValidationResult’s content and Rule together and is passed to the attached Validation.Error event to allow subscribers to perform related actions – e.g. log the error, display errors in a status panel, enable/disable controls.
IDataErrorInfo

Allows custom data classes to express data errors at an instance and/or field level. Whilst great in theory the real flaw (in my opinion) with this interface is that it only allows those errors to be expressed as strings.
This is limited because:

  1. We need to be capable of raising rich error information – for example – nominating the severity of the error, link to online help for further details or related content, provide access to automated response – e.g. apply default value. Sure we could embed an XML fragment describing richer content – but wouldn’t it have made more sense for this to be an object – even if the default controls simply performed a ToString() for their own limited error display?
  2. What if two fields combine to generate an error where their values conflict with one another. You can generate an error string for each but there really isn’t any neat way of associating them.

So what do I think a Validation System should provide? Here’s my required feature list drawing from my own experience of using these types of engines as the sole means for validating complex form data.

  1. Capable of highlighting controls that contain data which is in error, i.e. from something as simple as WinForm’s ErrorProvider through to WPF’s ErrorTemplate.
  2. Allow for multiple levels of validation severity. For example – the validation system should be capable of displaying not just errors, but warnings and even hints/suggestions.
  3. Allow for multiple level of validation priority. If multiple errors are raised the priority can be used to determine the order in which an error summary is built and displayed to the end-user – for example displaying only the highest priority message within a status panel.
  4. Simple validation logic should be defined wherever possible from property meta-data. For example, if a property is required to have a value an appropriate rule should be automatically applied (e.g. RequiredRule). For a rich data model this could include ranges (dates & numbers), numeric precision and string lengths.

Some ideas on how these requirements could be implemented with/around the WPF validation model.

  1. Create a generic ErrorTemplate that is applied using a style to all standard controls (overriding the default red rectangle around the control).
  2. Create a new abstract rule class derived from ValidationRule that adds properties for severity and priority.
  3. Create a new ValidationContent class that allows for rich error  information to be returned in a ValidationResult and becomes the object stored in ValidationError.ErrorContent.Error.
  4. Create a new interface IDataValidationInfo (?) that replace IDataErrorInfo exposing ValidationContent objects rather than just strings. [At the same time it should provide a method of being backwards compatible with IDataErrorInfo classes.]
  5. Create custom attributes that allow property meta-data to be defined within class models. Allow for automatic generation of rules based upon this meta-data (during Binding initialisation?).
  6. Use the Validation.Error attached routed event to automatically subscribe to all a containers validation. This is then used to display validation summary information within a status panel.
  7. Associated commands with rules – so that validation errors can be used to present the user the option of executing these commands.

At this stage this is all pretty “pie in the sky” stuff. Over the next couple of weeks I hope to post a few examples of some of this in action!

Validation Panel

The panel I’ve been working on to display rich validation messages is slowly coming along. I spent quite a bit of effort over the last two nights making it a well behaved “lookless” control.

The panel itself is simply a class derived from ItemsControl – has no XAML of its own. I then have a Themes/Generic.xaml file that contains the default rendering for the control as follows.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Spencen.Windows.Controls.Validation">
   <Style TargetType="{x:Type local:ValidationPanel}">
        <!-- Default property values -->
        <Setter Property="Background" 
Value="{DynamicResource {x:Static SystemColors.InfoBrushKey}}"/> <Setter Property="BorderBrush"
Value
="{DynamicResource {x:Static SystemColors.InfoTextBrushKey}}"/> <Setter Property="BorderThickness" Value="1.5"/> <Setter Property="Margin" Value="2,4"/> <Setter Property="Padding" Value="1"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ValidationPanel}"> <Border Background="{Binding RelativeSource={RelativeSource TemplatedParent},
Path
=Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Margin="{TemplateBinding Margin}" CornerRadius="2"> <ItemsPresenter Margin="{TemplateBinding Padding}"/> </Border> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate DataType="validation:ValidationContent"> <Grid Margin="4"> <Grid.Resources> <local:SeverityToImageConverter x:Key="imageConverter"/> </Grid.Resources> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Image Source="{Binding Path=Severity,
Converter
={StaticResource imageConverter}}"
Stretch="None" Margin="0,0,2,0"/> <TextBlock Text="{Binding Path=MessageText}" Grid.Column="1"/> <TextBlock Text="{Binding Path=MessageDetailText}"
Foreground
="DarkGray"
FontStyle
="Italic"
Grid.Column
="1" Grid.Row="1" TextWrapping="Wrap"/> </Grid> </DataTemplate> </Setter.Value> </Setter> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel/> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>

This displays the panel as shown below which is fairly standard for a message display area.

ThemedStatusPanel

I then went ahead and created a customised style that changes not just colours but also changes the layout a little. I finally came up with this “vista-ish” look – although its probably a little overdone for real-world use. In this version the secondary text (which in the contrived example is a little redundant) is displayed via a popup invoked by the Help image button.

StyledStatusPanel

Now I’m starting on some custom validation rules. One of the things that I want to achieve is to have the rules specify a set of optional commands. These commands will then be used by the Validation Panel to build a context menu (configurable UI of course). Example commands might be focus to control in error, apply default etc.

Since the look of each item in the panel is determined by a DataTemplate which itself is bound to a type – I also want to try creating a derived ValidationContent class so that I can try multiple item UIs within the same panel. This might be useful for example in displaying an “acknowledgement” panel that places the form “in error” until the user has acknowledged the message via a CheckBox. Could be used in scenarios like the typical “I acknowledge that I’ve read your 20 page EULA” message that is often displayed in installers.

WPF Validation Rules

Wow – just reading the section on Advanced DataBinding in the WPF Unleashed book. This talks about how to do validation during data binding – specifically by creating custom classes that inherit from ValidationRule and return a ValidationResult. Apart from being very déjà-vu – because at work we have our own validation rules engine that uses exactly the same class names it also sounds a little odd. Having a ValidationRules collection hanging right off the Binding itself – is that really the best place to define the rules?

My experience with our work validation engine is that certainly many of the rules – the simple ones – are actually derived directly from the binding. Therefore it would make sense to have them directly associated. Rules such as “is the field mandatory”, “what is the fixed range”, “what is the maximum text length”, “what is the precision associated with a number”. But what about inter-field rules such as “field A must be greater than field B”, “field C is mandatory when field D is set to value x”. Those are really entity based rules – not field based. Do we/could we put them at the DataBinding level?

I guess I’ll have to keep reading to find out :-p

————————

Ok – so now I’ve given this a quick test. To start with I’ve just created a simple class to bind to (Person) and hooked up a TextBox.

    <TextBox SpellCheck.IsEnabled="True">
        <TextBox.Text>
            <Binding Source="{StaticResource nos}" Path="FirstName" 
UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <valid:MandatoryRule/> </Binding.ValidationRules> <Binding.NotifyOnValidationError>true</Binding.NotifyOnValidationError> </Binding> </TextBox.Text> </TextBox>

Ok – the spell checking was just for fun.

Pretty longwinded isn’t it. Setting the NotifyOnValidationError means that I can hook my Status Panel up to the events so that entries are added and removed. The ValidationErrorEventArgs has a host of properties that allows me to determine exactly which Binding and UI element. Also, because the error content is an object I could provide my own Error class – so instead of just returning a ValidationResult with a string (as per example below) I could generate a rich error instance (with primary/secondary text, priority, help URL etc.)

My MandatoryRule is as simple as can be.

    public class MandatoryRule : ValidationRule
    {
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (value == null || object.Equals(value, string.Empty))
return new ValidationResult(false, "The field is mandatory.");
else
                return ValidationResult.ValidResult;
}
}

Hopefully I will put all this together and post soon with a working example of the Status Panel, together with some ideas on other features that could be included to make it more functional – such as clicking on a message to focus the associated UI element.

Restoring PCs using Windows Home Server

Over the last week I’ve had an unlucky streak with hardware on my home computers. Firstly my sons aging P3 tower had a hard disk failure. It wasn’t catastrophic but it was preventing new data from being written to the drive. So I copied everything off onto the Home Server’s shared folders.

Then I grabbed an old 6.4 Gb drive (yes they used to make them that small) and installed a vanilla copy of Windows XP. It took about 10 hours and 10 reboots to get this all the way up to Windows XP SP2 with IE 7 and all the latest patches. It also meant the drive had about 400 Mb free.

At this point I figure I’ll copy across a couple of files from the Home Server only to find its not responding. Turns out that the CPU (an old P4) has fried itself. Bugger.

So a trip to the local computer shop and I’ve got an el’ cheapo Core2Duo (4500), Asus motherboard (P5B-VM-SE) and 1 Gb of generic RAM. I rip out the old MB and replace with new components hoping and boot the machine. First thing I find is that it doesn’t even recognize the CPU. A quick download and flash of the latest motherboard BIOS fixes that, but the machine still won’t boot into Windows – reboots as soon as it hits the windows loader.

So I spend a few hours re-installing Windows Home Server. This is actually a lot less painful than Windows XP was – it has a neat feature that allows you to re-install the system partition without effecting any of the data backups or shares – very nice. During the installation though I can’t help noticing an odd “pfft” sound that comes from my son’s P3 which is supposed to be turned off. Turns out that the power supply (cranky old 230 W) has chosen this moment to commit suicide.

Next day – off to the shop again to get a new power supply. I opt for the slightly more expensive Thermaltake PSU with a 12cm fan. Theory being larger the fan slower the required rotation and therefore less noise. I was thinking I’d swap with the Home Server since that’s going to be running 24/7. However, surprisingly the new PSU was louder than the existing PSU in the Home Server that had two 8cm fans – weird.

So now my sons P3 machine has a whopping 550W PSU – major overkill – most of the connectors aren’t even compatible with the motherboard.

But now the cool bit.

  • I boot up the P3 connect to the Home Server and do a full system backup. Easy – does this very quickly across my 1Gb network (all my machines have 1Gb LAN) and connect to a 1Gb switch with the exception of the Home Theatre PC which is currently wireless only.
  • Next I power down the P3 – rip out the 6.4 Gb disk with the recently installed Windows XP and replace with a spare 30 Gb disk from my main workstation (I figure it can do with the 4 remaining newer drives).
  • Then I reboot the P3 using the Windows Home Server Restore CD. This takes a while to load – but when its done it then allows me to follow the prompts and restore the previous system image onto the new drive. It doesn’t care that the drive is a different size – as long as its >6 Gb. It even lets me go in and create partitions on the new drive before I do the restore.

Very nice! Well done Windows Home Server team!!