Daniel Cazzulino's Blog :

WPF (RSS)

WPF
For those that think Microsoft Connect is useless

A while back I reported both through my weblog and Microsoft Connect what I thought was a serious flaw in the WPF validation infrastructure for ValidationRule and Binding. The issue, in short was:

The validation check is invoked during any attempt to update the underlying data ... before a value converter is called (if present)...

Take special note that this was not some undocumented, strange behavior, but rather something that was explicitly explained on MSDN where the validation process was explained as part of the design.

But based on my feedback and the 13 other people that voted to fix the bug, it looks like they just did so (at least that's what the bug status shows).

Pretty significant IMO, especially since in my experience these kind of "breaking changes even if the existing behavior was already broken" issues rarely get fixed, no matter how obvious the error might be.

Continue blogging and bitching about stuff that bothers you, but don't forget to report it formally: it might make a difference and we may end up getting a better product from Microsoft (it may take years, but hey, it's a learning process!).

posted Friday, April 18, 2008 1:12 AM by kzu with 1 Comments

NavigationWindow, WinFormsHost and TextBoxes: backspace bug

WPF NavigationWindow is a very handy class that allows you to easily build Vista-like wizards, or any kind of window that resembles the browser-style navigation:

NavWindow   

The NavigationWindow will automatically handle the Backspace, Back/Next keys and perform the appropriate navigation on the window pages.

If you're combining this class with the WindowsFormsHost to integrate WinForms controls, you may hit a very annoying bug: if there are textboxes in your WinForm control, hitting Backspace while editing the input on it will cause the navigation window to navigate back, instead of deleting the text on the TextBox. Yikes!

Being WPF the new kid on the block, I was immediately tempted to blame it. Turns out it's a bug in the WinForms TextBoxBase :S.

You see, before WPF gets a chance to handle an input message, WindowsFormsHost tries to determine whether any contained control is interested in handling the message first and gives it the option to do that right away. This is done by calling the WinForms Control.PreProcessControlMessage() which ultimately calls the virtual Control.IsInputKey which controls use to determine a particular key is part of their input processing. The problem is that TextBoxBase does not say it's interested in handling the Backspace key (but it does so for Esc, Tab, Home, End, etc., and inherits the text keys from the base Control class implementation of IsInputKey).

Therefore, the WindowsFormsHost doesn't do anything further with the message, and the message enters the WPF input system, where it induces events tunneled and bubbled across the element tree. Eventually, NavigationWindow handles the key thanks to the built-in CommandBinding for navigating back. Bummer :(.

Fortunately, there are a couple workarounds:

  1. Create your own TextBox-derived control that fixes the IsInputKey implementation and use that in your controls:
    public class TextBox2 : TextBox 
    {
      protected override bool IsInputKey(Keys keyData)
      {
        return base.IsInputKey(keyData) || keyData == Keys.Back;
      }
    };
  2. Cancel NavigationWindow's CommandBinding for the backspace key by doing this in the constructor of your NavigationWindow-derived class:
    InputBindings.Add(new KeyBinding(ApplicationCommands.NotACommand, new KeyGesture(Key.Back))); 

     

I prefer the latter, as it doesn't require you to modify your existing WinForms controls. On the other hand, it removes the Backspace gesture for navigating back, but that's not too bad as I doubt users are actually going to miss it (how many people navigate back in the browser by pressing Backspace anyway?)

I created a small repro and reported this bug through Connect. Feel free to vote for it ;)

posted Wednesday, December 26, 2007 10:20 AM by kzu with 1 Comments

How to compile and run ALL WPF samples in the Windows SDK with a single command

Just issue the following PowerShell one-liner, and you'll compile and run each sample in the SDK (enter all in one line; broken here for readability):

PS C:\WinFx Samples\WPFSamples\AppModel\> 
gci -i *.csproj -r |
foreach
{
pushd ([System.IO.Path]::GetDirectoryName($_.FullName));
msbuild $_.fullname;
(gci -i *.exe -r |
%{ &$_.fullname; read-host; });
popd;
$_;
}

 

"WinFx Samples" is the folder where you installed the samples. It also works from a subdirectory, as you can see, so that you only run the subset of samples you're interested in. Executables may launch twice (from obj and bin outputs) and in some cases a dependent project might not get built before the main one, but hey, it's just a quick trick ;). The process will pause after executing each sample.

Very useful if you're just playing with the technologies and want to get a quick overview through samples of what's possible.

posted Thursday, November 15, 2007 8:13 PM by kzu with 2 Comments

Automatic generation of data-binding interfaces for data context objects

From the new Clarius Labs release:

XamlBinding Custom Tool

This custom tool will generate a partial class file implementing INotifyPropertyChange as well as a strongly-typed event for each property declared in the file it's applied to.
This is very useful when creating models or entities that are used in data-binding scenarios, and where an associated presenter needs to perform certain logic when a given property changes.


Communicating through these strong-typed events prevents tight coupling between the presenter and the UI, which now communicate exclusively through the model/data context.
A must-have for anyone doing "Binding Oriented Programming" ;)


The code generator solves the problem of having the presenter attach to the generic INotifyPropertyChanged.PropertyChanged event and checking the property by name, which must be kept in sync with the class definition and doesn't participate in refactorings.


It will also solve the initialization sequence and validation (post deserialization and afterwards) problem by implementing ISupportInitialize, ISupportInitializeNotification and IChangeTracking, which allows it to track changes automatically on its members and nested values. The public interface of your object remains uncluttered by implementing most of these privately. The data context class can simply call the provided EnsureValid at the beginning of each method call to make sure that the class has been properly initialized, and that if it's dirty, it's re-validated.


A DoValidate method is added to the main class to implement the actual property validation (where you could use the Standalone Validation Block for example), as well as RaiseXXChanged method calls on each property setter.


Finally, the generated code doesn't depend on anything other than System.ComponentModel, so WPF is not even required to use the codegen for other data-binding scenarios (WinForms should work fine).


Installation: run the MSI, or compile the included solution.
Usage: assign the value XamlBinding to any code file in VS. A corresponding file ending in ".XamlBinding.cs" (or .vb) will be generated automatically everytime the main file changes.

This release supports both VB and C#.

Enjoy!

posted Thursday, September 27, 2007 10:44 PM by kzu with 2 Comments

Evolving community guidelines on XAML and WPF

I just found the following excelent guidelines (especially the ones on resources organization) at Paul Stovell's blog.

I think it would be great to have community-developed guidelines on this topic. I've proposed to Paul to use Jottit, which is brain dead simple and uses the increasingly popular Markdown format.

Would be nice to point everyone to http://wpf.jottit.com/ and http://xaml.jottit.com/ for this kind of advice :)

posted Wednesday, September 26, 2007 9:30 PM by kzu with 1 Comments

Automatic input validation in WPF with data binding and Enterprise Library Validation Application Block

WPF provides validation infrastructure for databinding scenarios through ValidationRule objects. Only one built-in rule is provided, and you're expected to write most of these yourself. The way they work is by assigning one or more explicit rules to a binding:

<TextBox ...>
  <TextBox.Text>
    <Binding .>
      <Binding.ValidationRules>
        <local:JpgValidationRule/>
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

[Example from Adam Nathan's excelent book on WPF]

Note that the syntax is much more involved than the simple non-validating binding:

<TextBox Text="{Binding ...}">
</TextBox>

Another consequence of the provided support is that even if you reuse the data context (i.e. you provide more than one screen that binds to a given object type, say "Customer" object) in more than one editing scenario, you will need to duplicate the validators and make sure you keep them in sync. Also, you will typically be performing the same validation again in the object itself (i.e. the above binding probably sets a "Photo" string property), so you either take a dependency on WPF from your entities project just to call the same validation rules, or you duplicate the code to perform the validation (or you make your rules just expose a WPF interface over the same objects). In any case, there's no straight-forward way to reuse the logic, and maintaining the XAML and entities internal validation rules in sync is far from ideal.

The Microsoft Enterprise Library Validation Block (EntLib VAB) solves this problem by providing attribute (or configuration) driven rules that you can validate on the UI as well as on your entities. For example:

				public
				class
				Customer
				
				{
  privatestring firstName;

  [StringLengthValidator(1, RangeBoundaryType.Inclusive, 0, RangeBoundaryType.Ignore)]
  [NotNullValidator]
  publicstring FirstName

The code above specifies that the FirstName property must be a non-null, non-empty string. You could very easily create a custom validation rule such as NotNullOrEmptyValidator ;), but you get the idea.

EntLib VAB provides integration with WinForms and ASP.NET validation architectures, but not for WPF. Up to now, that is ;).

I've been working for the past few days on getting a kick-ass integration with WPF. It wasn't easy, and I found a couple not-so-nice things in the way, but I finally got the following working flawlessly (and without any hacks):

<Window ... xmlns:v="http://www.codeplex.com/entlibcontrib">
  <Grid>
    ...
    <Label Content="First Name:"/>
    <TextBox Text="{v:ValidationBinding FirstName}" .../>
    ...
    <TextBox Text="{v:ValidationBinding Address.USState}" .../>
    ...
  </Grid>
</Window>

This sample markup and the class above are part of a sample available with the download.

You can now do a simple search&replace of Binding with v:ValidationBinding and that's it. If your data context objects (or entities) provide validation attributes, they will get automatically applied to the binding, and all the WPF-specific handling on the UI for showing the errors and styling the elements with errors will be available to you for free.

 

The ValidationBinding is nothing more than a MarkupExtension that acts as a decorator for a Binding. Hence, the full data binding behavior is preserved, as I'm basically returning from my extension the result of evaluating the binding I'm decorating (prior to attaching my validation rule). From that point on, it's plain built-in validation rules and a few creative tricks to get around EntLib VAB's a bit weird "integration" model. It may be interesting to look for someone looking to implement their own markup extensions. In order to allow for the drop-in replacement scenario with the Binding class, I also expose all of the public properties of a binding, so that if you're using any of them, you get full fidelity behavior as they are all just pass-through getters/setters to the inner instance of the binding I'm constructing.

 

I've contributed this code to the EntLib Contrib project as part the Standalone Validation Application Block, which is a version of the VAB that doesn't depend on configuration at all. I've written about why XAML makes System.Configuration and Enterprise Library Configuration obsolete and why we need an EntLib Standalone Validation Application Block before. I may integrate this with the official EntLib 3.1, but it's not a high priority for me as I don't believe we need all the System.Configuration/ObjectBuilder baggage just for validation. If there's enough demand for it through the project discussions, though, I'm sure someone (maybe myself?) will get it done eventually.

 

Go get the release, and enjoy developing apps with full input validation and data binding in (almost) pure markup :

posted Wednesday, September 26, 2007 8:25 PM by kzu with 1 Comments

Serious flaw in WPF validation infrastructure for ValidationRule and Binding

Adam Nathan's excelent book on WPF states:

The validation check is invoked during any attempt to update the underlying data ... before a value converter is called (if present)...

This is further reinforced on MSDN where the validation process is explained:

image 

I can't understand how this design decision was made (it seems to be very much a rational decision, given how well documented it is).

Think about this scenario: you want to validate an integer value for a property (say, its range). There is a built-in converter for integers (but this could be a custom value converter, if it was your own type) that will ultimately assign a value of the right type to the property.

The validation routine should deal only with checking the range of an integer, not about how to convert it from whichever value it's passed-in by the binding target (i.e. the textbox control), which is already a responsibility of the value converter. If it has to perform conversion of the value prior to validating it, then a double conversion will happen if the value turns out to be valid.

What's worse, the validation rules have no way of accessing the value converter associated with the binding, so you'll end up either hardcoding which value converter to use inside the validator, or having to sync both manually (make validator code and XAML match).

 

Consider the alternative: first, the value converter tries to convert. Say It fails. It's like a validation error, but it's a precondition to validation that failed. With this approach, the validator can rely on the incoming value to always be of the appropriate type. A much better approach IMO.

 

I'm still enjoying XAML/WPF very much, but this is the second "not-cool" moment I had in a single week :(.

It's probably useless, but if you wanna vote to get this changed, go ahead. Thanks.

posted Tuesday, September 25, 2007 8:21 PM by kzu with 3 Comments

Why we need an EntLib Standalone Validation Application Block

In my previous post about XAML and its future as a domain model/DSL serialization format, I've argued that System.Configuration as well as Enterprise Library Configuration (part of the core of EntLib) will soon become irrelevant.

The caveat is that now you need to design your classes a bit differently. No more const