A place for spare thoughts

01/05/2014

Creating custom UIA patterns in managed code

Filed under: automation, wpf — Ivan Danilov @ 15:32

I’ve finished first working version of the library that makes subject easily feasible. Here is the implementation along with some documentation: https://github.com/ivan-danilov/uia-custom-pattern-managed#creating-custom-uia-patterns-and-properties-with-c

My target is to make it work smoothly with WPF, but for WinForms or with bare UIA it works as well.

21/05/2013

WPF UI Validation technique

Filed under: c#, wpf — Ivan Danilov @ 13:51

WPF provides several methods of validation, most common are implementing IDataErrorInfo on ViewModel, implementing custom ValidationRule, use ValidatesOnException whatever.

But for MVVM pattern really only IDataErrorInfor is good. The problem with other approaches – well, the VM can’t know with them if error happened. Yeah, user gets error indication, error is handled… but the VM thinks everything is good. Suppose VM controls if OK button is enabled or disabled (e.g. via CanExecute of bound command) – how could VM know when to disable the button if it doesn’t know if error happened?

Let’s try to imagine absolutely trivial example: window with TextBox and a Button. User should type integer in the TextBox and click the button. If user doesn’t enter a number at all or entered some invalid value (like ‘abc’ or non-integer like ‘1.23’) – button should be disabled and TextBox should have normal error notification (default WPF red outline is ok).

The task is trivial, so the code should better not be complicated as well. Of course we want MVVM-ish thing, so let’s write a VM:

class VM
{
    public int Value { get; set; }
    public ICommand Ok { get; set; }
}

VM most probably needs to implement INotifyPropertyChanged for its properties, but it is not the case here, so I’ve omitted these. Can you see the problem already? Value has int type. When user types ‘abc’ in the TextBox – Value won’t receive changes until value becomes parseable integer again. Binding just can’t pass them to VM – it has no means to do so. And thus we can’t notify Ok command that it can’t be executed right now. Moreover, if OK button is supposed to save something… imagine a scenario: user entered 100 to the TextBox, this value has propagated to Value property, then user accidentaly typed ‘o’ (letter o) instead of ‘0’ (zero) – they are pretty close on my keyboard – and clicked OK. Oops. We just overwritten old data with 100, when user thought it will be 1000. Definitely not good.

So, what is the solution? One apparent one is to change Value’s type: let it be a string. We can parse it in the VM and determine if it is correct, and disable Ok command. It will work, of course, but if you have two dozens of such pseudo-integers – VM becomes a pile of ToString() and Int32.Parse() calls here and there, which hides all the logic. A mess, shortly said.

What is the problem we’re trying to solve, exactly? Inability of View to notify ViewModel that error has happened. Ok. Lets pretend we found a place in the View that knows about the problem. How could it notify the VM? Well, View has very precise knowledge about its VM – it is the DataContext. But the DataContext is of type object… making View know precise type of its VM is probably not a good idea (besides it will make the solution require separate modification for each case), so we will encapsulate details of error notifications in the interface:

    public interface IUIValidationErrorSink
    {
        void AddUIValidationError(string propertyPath, string errorContent);
        void RemoveUIValidationError(string propertyPath);
    }

Don’t be amused where this precise arguments are came from – it will become clear after a couple of minutes. So, if our validation mechanism could get instanse of IUIValidationErrorSink object – it could notify interested parties that new error appeared or existing error is gone. So far so good.

VM will implement this in very straightforward way:

class VM : IUIValidationErrorSink
{
    private Dictionary<string, string> _uiErrors = new Dictionary<string, string>();

    public VM()
    {
        Ok = new RelayCommand(DoOk, CanOk); // RelayCommand is from famous John Smith's MVVM article here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090051
    }

    public int Value { get; set; }
    public ICommand Ok { get; set; }

    private void DoOk()
    {
        // Do something useful
    }

    private bool CanOk(object _)
    {
        return _uiErrors.Empty();
    }

    void IUIValidationErrorSink.AddUIValidationError(string propertyPath, string errorContent)
    {
        UIErrors[propertyPath] = errorContent;
    }

    void IUIValidationErrorSink.RemoveUIValidationError(string propertyPath)
    {
        UIErrors.Remove(propertyPath);
    }
}

Another problem is how we would find which control’s DataContext we should take? For example, if you have ItemsControl of something editable – each item has its own DataContext.

To answer this question we need to know a bit about WPF’s Binding Validation mechanism. It is implemented via Routed Events, particularly ErrorEvent in the System.Windows.Controls.Validation class (if you want to know more about Routed Events – you may start here). ErrorEvent is raised in the WPF Binding mechanism whenever error appears or disappears (actually, Binding calls Validation.AddValidationError and Validation.RemoveValidationError methods, which in turn call RaiseEvent). The target of this routed event is the DependenencyObject that owns bound DependencyProperty. As this event has Bubbling strategy, it then re-raised for each parent control in the Visual Tree from target until either the root is reached or someone marks event as Handled.

If only we could set routed event handler for ErrorEvent somewhere near the top of the View’s visual tree, where we always know our ViewModel… The good news are that we can – attached properties make this quite easy:

        public static readonly DependencyProperty IsUIValidationErrorSinkProperty =
            DependencyProperty.RegisterAttached("IsUIValidationErrorSink",
                                                typeof (bool),
                                                typeof (UIValidation),
                                                new PropertyMetadata(false, IsErrorSinkPropertyChangedCallback));

        public static bool GetIsUIValidationErrorSink(DependencyObject obj)
        {
            return (bool) obj.GetValue(IsUIValidationErrorSinkProperty);
        }

        public static void SetIsUIValidationErrorSink(DependencyObject obj, object value)
        {
            obj.SetValue(IsUIValidationErrorSinkProperty, value);
        }

        private static void IsErrorSinkPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var control = dependencyObject as FrameworkElement;
            if (control == null)
                throw new ArgumentException("IsUIValidationErrorSink property could be attached only to FrameworkElement descendants");

            control.AddHandler(Validation.ErrorEvent, HandleErrorEvent);
        }

Here we restrict the property to FrameworkElement because we need access to FrameworkElement.DataContext. Assuming we have written UIValidationRule already (see below), our handler might look like this:

        private static void HandleErrorEvent(object sender, RoutedEventArgs e)
        {
            var args = (ValidationErrorEventArgs) e;
            if (!(args.Error.RuleInError is UIValidationRule)) return;
            
            var sinkControl = (FrameworkElement) sender;
            var sink = sinkControl.DataContext as IUIValidationErrorSink;
            if (sink == null)
            {
                PresentationTraceSources.DataBindingSource.TraceEvent(TraceEventType.Error, 0, "UIValidation.IsUIValidationErrorSink attached property's HandleError encountered an error: DataContext does not implement IUIValidationErrorSink");
                return;
            }

            // filter out rules that are not UiValidationRule - we're handling only these
            var error = Validation.GetErrors((DependencyObject)args.OriginalSource)
                .FirstOrDefault(err => err.RuleInError is UIValidationRule);
            
            var bindingExpression = (BindingExpression) args.Error.BindingInError;
            string propertyPath = bindingExpression.ParentBinding.Path.Path;

            if (error == null)
            {
                sink.RemoveUIValidationError(propertyPath);
            }
            else
            {
                var errorMessage = (string) error.ErrorContent;
                sink.AddUIValidationError(propertyPath, errorMessage);
            }

            args.Handled = true;
        }

Now we need to write last piece – UIValidationRule which will actually validate the input. The goal here is to make it as easy to use and extensible as possible: first because we don’t won’t to use clumsy long XAML code pieces and second because we may want to write many slightly different rules: for ints, doubles, DateTimes etc. Also we want error messages to be customizable and localizable. Hence UIValidationRule will be an abstract base class which will be extended then.

My first idea was to make one descendant of this abstract class for each rule I needed. Though it turned out these descendants were pretty much the same and had almost everything duplicated – the only real difference was use of Int32.TryParse vs Double.TryParse. So I’ve decided to have single descendant of UIValidationRule which takes something akin to TryParse delegate as an argument:

    public abstract class UIValidationRule : ValidationRule
    {
        public string DefaultErrorMessage { get; set; }
    }

    public sealed class RelayUIValidationRule : UIValidationRule
    {
        private readonly Func<string, CultureInfo, string> _validator;

        /// <param name="validator">Mapper from string value to error or null if validation succeeded</param>
        public RelayUIValidationRule(Func<string, CultureInfo, string> validator)
        {
            _validator = validator;
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            var str = (string) value;
            string err = _validator(str, cultureInfo);
            return err == null ? ValidationResult.ValidResult : new ValidationResult(false, err);
        }
    }

Here Func<string, CultureInfo, string> takes string representation and culture info and returns null if validation succeeds and not null string with error message otherwise.

Also ‘normal’ way of using binding validation rules usually looks like this:

<TextBox>
    <Binding Path="Value" NotifyOnValidationError="True">
        <Binding.ValidationRules>
            <local:MyBindingValidationRule />
        </Binding.ValidationRules>
    </Binding>
</TextBox>

Ahem, really? 7 lines of XAML code to bind one value, not mentioning boilerplate NotifyOnValidationError="True"? No-no-no, it is totally unacceptable. Lets see if we could find a better, more terse way. Actually it is not that hard, if we assume control can’t have two UI validation rules at once (hey, this poor string shouldn’t be parsable as double and DateTime at the same time!):

    public class ValidatedBinding : Binding
    {
        private UIValidationRule _uiValidation;

        public ValidatedBinding()
        {
            NotifyOnValidationError = true;
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        }

        public UIValidationRule UIValidation
        {
            get { return _uiValidation; }
            set
            {
                if (_uiValidation != null)
                    ValidationRules.Remove(_uiValidation);
                _uiValidation = value;
                if (_uiValidation != null)
                    ValidationRules.Add(_uiValidation);
            }
        }
    }

And final step: make instantiation of validation rules driven by MarkupExtensions:

    internal delegate bool TryParseFunc<T>(string source, CultureInfo cultureInfo, out T result);

    public abstract class UIValidationExtensionBase<T> : MarkupExtension
    {
        private readonly string _customErrorMessage;
        private readonly TryParseFunc<T> _tryParseFunc;

        internal UIValidationExtensionBase(string customErrorMessage, TryParseFunc<T> tryParseFunc)
        {
            _customErrorMessage = customErrorMessage;
            _tryParseFunc = tryParseFunc;
        }

        /// <summary>
        /// Specifies that empty string and null values should be allowed by the validation mechanism. 
        /// False by default.
        /// </summary>
        public bool AllowNulls { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            Func<string, CultureInfo, string> validation =
                (s, c) =>
                    {
                        if (AllowNulls && String.IsNullOrEmpty(s))
                            return null;
                        T result;
                        bool success = _tryParseFunc(s, c, out result);
                        return success ? null : _customErrorMessage;
                    };

            return new RelayUIValidationRule(validation)
                       {
                           DefaultErrorMessage = _customErrorMessage
                       };
        }
    }

    [MarkupExtensionReturnType(typeof (UIValidationRule))]
    public class IntUIValidationExtension : UIValidationExtensionBase<int>
    {
        public IntUIValidationExtension()
            : this("Incorrect number format")
        {
        }

        public IntUIValidationExtension(string customErrorMessage)
            : base(customErrorMessage, (string s, CultureInfo c, out int result) => int.TryParse(s, NumberStyles.Integer, c, out result))
        {
        }
    }

    [MarkupExtensionReturnType(typeof (UIValidationRule))]
    public class DateTimeUIValidationExtension : UIValidationExtensionBase<DateTime>
    {
        public DateTimeUIValidationExtension()
            : this("Incorrect date/time format")
        {
        }

        public DateTimeUIValidationExtension(string customErrorMessage)
            : base(customErrorMessage, (string s, CultureInfo c, out DateTime result) => DateTime.TryParse(s, c, DateTimeStyles.None, out result))
        {
        }
    }

    // I think you could come up with other extensions as well 🙂

And finally, the first clumsy syntax with 7 lines transformed into beautiful one-liner:

<TextBox Text="{WpfValidation:ValidatedBinding UIValidation={WpfValidation:IntUIValidation}, Path=Value" />

Well, don’t forget to put UIValidation.IsUIValidationErrorSink="True" somewhere in your XAML.

17/04/2012

Binding to WPF TextBox seems to be broken in .NET 4.5 Beta

Filed under: wpf — Ivan Danilov @ 15:18

Recently I found that update from .NET 4.0 to .NET 4.5 Beta brings one nasty bug with it to the WPF. As Scott mentioned, .NET 4.5 is in-place upgrade to .NET 4.0, thus now I experience the same problem in any app targeted at .NET 4.0 as well.

OK, let’s go closer to the actual problem.

Create new WPF application, in MainWindow.xaml put the following:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <Grid>
    <TextBox Text="{Binding Path=Prop, UpdateSourceTrigger=PropertyChanged}" />
  </Grid>
</Window>

And here is MainWindow.xaml.cs:

using System.Windows.Controls;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public decimal Prop { get; set; }
    }
}

That’s all. Now, run the application. You will have TextBox stretched to the entire window with ‘0’ inside. Try to enter decimal dot (or whatever you have on your current culture for separating integer part from fractional). Nothing happens.

Now go to project properties and switch target framework to .NET 3.5 (you have to delete some references that do not exist in that framework, but I didn’t use them here anyway, so it is OK). Run the app – everything will work fine, you can enter decimal dot.

I suppose the problem is somewhere in property changing/coercion mechanism: WPF tries to parse value ‘0.’ as decimal, it succeeds and TextBox’s contents changed back to ‘0’ which is decimal value converted to string. It is also indirectly proven by the fact that if you have ‘0’ and press ‘1’ – you will have ‘1’ instead of ’01’ which one could expect. Similarly, you can’t put ‘+’ sign before number, but can put ‘-‘ sign before non-zero number. And you can’t put any sign before zero. And even more vivid proof – if you have any invalid value (i.e. that can’t be parsed as decimal) – you can do any edits you like and they are handled correctly.

Here is feedback at MS connect site about the problem.

UPD: At connect MS replied that 4.0 behavior was actually a bug and they fixed it in 4.5. In fact the fix is worse from usability point than bug was as it seems to me… see the discussion at MS Connect site (link above) for details.

27/02/2012

Weak delegates for non-standard event handlers (e.g. WPF)

Filed under: wpf — Ivan Danilov @ 14:04

About Weak delegates there’s many articles lurking around the Internet. The most beautiful IMO is this one. So, I assume that you already read it and won’t repeat that info.

So, some time ago (pretty much time, actually, just hadn’t time to write earlier), inspired by the beauty of the article I happily copied MakeWeak extension method to our codebase… just to find out that the most frequently used WPF event is declared as

event PropertyChangedEventHandler PropertyChanged;

public delegate void PropertyChangedEventHandler(object sender,
                                                 PropertyChangedEventArgs e);

Remember Dustin’s complaints about MS not following their own recommendations? That’s it. Problem. Why is it not declared as that?

event EventHandler<PropertyChangedEventArgs> PropertyChanged;

Who knows? I’m interested too. Can’t see any problems and one type to load less for CLR. But anyway, if I want to work with WPF – I should invent something about the problem.

And so the saga begins… oops, it is not from this story, sorry 🙂

So, lets define first what our weak events MUST HAVE (i.e. without what they wouldn’t be useful at all). For me these requirements include at least:

  • It should be weak and should be working! (surprise, eh?)
  • I shouldn’t specify type parameters explicitly, they should be fully inferred from usage;
  • I want static check that actual unsubscription is correctly typed and I don’t unsubscribe delegate of wrong type (so, basically I want be at least minimally defended against InvalidCaseException at runtime);
  • Performance should be at least the same order as with normal delegates, i.e. no hardcore reflection on every event invocation.

The very first problem is to obtain original event actually. Originally MakeWeak defined as

public static EventHandler<TEventArgs> MakeWeak<TEventArgs>(
        this EventHandler<TEventArgs> eventHandler,
        UnregisterCallback<TEventArgs> unregister)
    where TEventArgs : EventArgs

See the problem? With non-standard delegates we don’t have EventHandler<TArgs>. And we have to save that delegate later after ‘casting’ it to OpenEventHandler in the WeakEventHandler class – there we need MethodInfo instance that originally obtained via eventHandler.Method property. So the idea – lets parametrize this method with one yet type parameter, like that:

public static EventHandler<TEventArgs> MyMakeWeak<THandler, TEventArgs>(
        this EventHandler<TEventArgs> eventHandler,
        UnregisterCallback<TEventArgs> unregister)
    where THandler : Delegate
    where TEventArgs : EventArgs

So we pass eventHandler and Delegate has Method property as well, so it should be fine… nope, it’s not. If you try to compile that you have “Constraint cannot be special class ‘System.Delegate'” from compiler. Eric Lippert said that there’s no technical reason to not support such syntax, but it is just not needed often, so it is pretty low on priority list. No luck! I have to thought out something else.

OK, let’s sacrifice type safety here and make extension method accept any type T:

TEventHandler MyMakeWeakTEventHandler>(this TEventHandler eventHandler, 
                                       Action<TEventHandler> unregister)

It is not a big deal and doesn’t break our requirement – remember, we will use this method only with that syntax:

obj.PropertyChanged += new PropertyChangedEventHandler(MyMethod)
    .MyMakeWeak(h => obj.PropertyChanged -= h);

In other words, if we try to pass not PropertyChangedEventHandler but some wrong class there, it will violate types at += operator because we’re returning exactly that type that was passed to our extension method.

So, what will we have then? We can rely on the fact that TEventHandler in reality is derived from Delegate class and can be cast to it. Yes, it is possible to misuse that method and get exception at runtime only, but it is hard to do unintentionally, so I’m fine with that.

The next problem: we don’t know argument type from the start. Before it was TEventArgs : EventArgs, but now we don’t have such thing. Well, if we can cast our param to Delegate – we can know list of its parameters via Delegate.Method.GetParameters()[index].ParameterType. Not very pretty and we don’t know concrete signature of the delegate – even number of parameters… Wait, we do know number of parameters almost always – fortunately, WPF team didn’t abandon guidelines totally and their delegates have normal void (object sender, TEventArgs e) signature everywhere. That’s something. Yep, again, it won’t work absolutely everywhere, but in worst case I can extend this approach in the same ugly way as Func can have various number of type arguments (no, I will not do this here because I don’t need this – at least I haven’t so far).

So, MyWeakEventHandler will have one generic type parameter more as it needs to know not only receiver type and event args type, but exact delegate type as well.

So far, so good. It seems everything is pretty much clear with MyMakeWeak method – at least if it will work in the end (remember first requirement?). And one last stroke: instead of strange MyMakeWeak I finally named it MakeWeakSpecial. While I could name it MakeWeak too as original one (which stays untouched) it would bring to scene C#’s overload resolution rules which are insanely complex and sometimes very confusing in the presence of generics. So I’ve decided to name it differently just to be sure what I’m using. Here’s what we have:

public static TEventHandler MakeWeakSpecial<TEventHandler>(this TEventHandler eventHandler, Action<TEventHandler> unregister)
{
    if (eventHandler == null)
        throw new ArgumentNullException("eventHandler");

    var ehDelegate = (Delegate) (object) eventHandler;
    var eventArgsType = ehDelegate.Method.GetParameters()[1].ParameterType;
    Type wehType = typeof(WeakEventHandlerSpecial<,,>)
        .MakeGenericType(ehDelegate.Method.DeclaringType, 
                         typeof(TEventHandler), 
                         eventArgsType);

    ConstructorInfo wehConstructor = wehType.GetConstructor(new[]
                                                            {
                                                                typeof(Delegate), 
                                                                typeof(Action<object>) 
                                                            });

    Debug.Assert(wehConstructor != null, "Something went wrong. There should be constructor with these types");

    var weh = (IWeakEventHandlerSpecial<TEventHandler>)wehConstructor
        .Invoke(new object[] 
                {
                    eventHandler, 
                    (Action<object>)(o => unregister((TEventHandler) o)) 
                });

    return weh.Handler;
}

Well, lets go to WeakEventHandlerSpecial<T, TEventHandler, TEventArgs>. The only problem we have there is that TEventHandler has no relation to TEventArgs. So, original concise _handler = Invoke; is not applicable, as _handler has type TEventHandler and Invoke is method group with (object, TEventArgs) signature. It is not hard problem: we just need to obtain current instance’s type, find its method "Invoke" and dynamically create delegate of type TEventHandler with Delegate.CreateDelegate. And what about performance, you could ask? Well, it is another costly operation. But we’re still in the code region that will be executed once for a subscription, NOT once per event occurring. So I deem it reasonable (Again, in the worst case if I need to optimize these at some point – nobody prevents me from some caching strategy or creating compiled Expression or any other mechanism – thus, from ‘once per subscription’ it will be ‘once per given three types’).

And so, finally, here you can get results (WeakDelegates.zip) with several unit tests: link.

And in case you don’t want to download something and want just a quick-look at what I have as result – you have this gist.

And regarding requirements:

1. It’s working. Unit tests are swearing that it is so.
2. While using I’m not forced to specify anything.
3. In the only real-world usage types are checked. Other cases are not, but it is ok.
4. There’s somewhat more reflection than it was in the original weak events, but only slightly.

I think my own requirements are pretty much fulfilled. 🙂

27/09/2011

WPF 4.5 supports MarkupExtension in the event properties

Filed under: wpf — Ivan Danilov @ 08:22

At last! Since the beginning of MVVM pattern it was some kind of a miss in the framework: when control supports commands you have more or less convenient model of work – create command in the ViewModel and bind control’s action to it. But if you want to use some event as a trigger for command – you can say goodbye to simplicity and conciseness of your code.

The cleanest approach I am aware of is to declare some attached behavior that will act as a bridge between control’s events (as it will subscribe and unsubscribe when needed) and ViewModel’s commands (receive command instance from binding and invoke it when event is raised). This approach has one major downside – you need to write new attached behavior for each control/event pair you need to use. It is easy, boring and error-prone.

For RoutedEvents there’s better option as we have some means to pinpoint event’s tail directly in XAML with compile-time checking. I won’t stop on it in details as you could read about it here and here or here.

There’s of course ‘heavy artillery’ variant in form of reflection (make attached behavior and specify event name as string), but it doesn’t have compile-time checking, IntelliSense and many other useful things so I don’t consider it a viable approach at all in day-to-day work.

With WPF 4.5 things are finally became better. Now you can write MarkupExtensions for events thus the main problem of the first approach (namely: impossibility to specify event in the clean manner for attached behavior) is defeated. Jonathan Antoine already wrote an example how to use this new feature here and here. He is showing only general technique, but replacing method call with command invocation seems almost trivial. What I’d like to have is something as below code:

<Grid PreviewMouseDown="{custMarkup:InvokeCommand Command={Binding MyCommand}, CommandParameter=Whatever}" />

23/08/2011

Checking correctness of DependencyProperty declarations

Filed under: wpf — Ivan Danilov @ 19:44

DependencyProperty declaration is a fairly standard action and it is often performed with some kind of templates or snippets. Name in DependencyProperty.Register call should match property name itself, some methods should be declared, it should be most times static and readonly etc. Also if you declare read-only DP – you want Key to be non-public and DP itself to be public (otherwise why to declare it as read-only in first place?)

So, simple rule to check some of these things is below. It is almost trivial to plug it in SourceChecker I described before (actually we have this rule there).

public class AttachedPropertiesNamedCorrectlyRule
{
    private static readonly Regex PropertyPattern = new Regex(
        @"(?public\s+)?(?(static\s+)?(readonly\s+)?(static\s+)?)" + // match any order/presence of modifiers
        @"DependencyProperty\s+(?\w+)\s*" + // propname is identifier name, should be XxxProperty
        @"(" + // match registration assignment, assignment from property key or just ';' here
        @"   (?" +
        @"      =\s*DependencyProperty\.Register(Attached)?\s*\(\s*" + // match attached properties also
        @"      ""(?[^""]+)""" +
        @"   )" +
        @"|" +
        @"   (?" +
        @"      =\s*(?\w+)\.DependencyProperty\s*;" +
        @"   )" +
        @"|" +
        @"   (?;)" +
        @")",
        RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.ExplicitCapture);

    private static readonly Regex PropertyKeyPattern = new Regex(
        @"(?public\s+)?(?(static\s+)?(readonly\s+)?(static\s+)?)" + // match any order/presence of modifiers
        @"DependencyPropertyKey\s+(?\w+)\s*" + // propname is identifier name, should be XxxProperty
        @"(" + // match assignment or just ';' here
        @"   (?" +
        @"      =\s*DependencyProperty\.Register(Attached)?ReadOnly\s*\(\s*" + // match attached keys also
        @"      ""(?[^""]+)""" +
        @"   )" +
        @"|" +
        @"   (?;)" +
        @")",
        RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.ExplicitCapture);

    public IEnumerable Check(string cscode)
    {
        var errors = new List<string>();

        CheckDependencyProperties(cscode, errors);
        CheckDependencyPropertyKeys(cscode, errors);

        return errors;
    }

    private static void CheckDependencyProperties(string sourceText, List<string> errors)
    {
        Match matchResults = PropertyPattern.Match(sourceText);
        while (matchResults.Success)
        {
            var propname = matchResults.Groups["propname"].Value;
            var modifiers = matchResults.Groups["modifiers"].Value;
            bool isPublic = matchResults.Groups["publicity"].Success;
            bool noInitializer = matchResults.Groups["noInitializer"].Success;
            bool initializedFromKey = matchResults.Groups["assignmentFromKey"].Success;
            bool isStatic = modifiers.Contains("static");
            bool isReadonly = modifiers.Contains("readonly");

            if (!isPublic)
            {
                // probably some internal usage passed in instance constructor, can't say if it is wrong
                matchResults = matchResults.NextMatch();
                continue;
            }

            if (!isStatic)
                errors.Add(string.Format("DependencyProperty {0} is not marked as static", propname));
            if (!isReadonly)
                errors.Add(string.Format("DependencyProperty {0} is not marked as readonly", propname));

            // Initialization in static constructor should be avoided because of performance impact of static ctor presence
            // See here: http://stackoverflow.com/questions/2921828/static-constructors-cause-a-performance-over-head
            // Also SourceChecker can't check such initialization reliably (for example with partial classes static ctor 
            // could be in other file) and ensure that property name matches string given as parameter
            if (noInitializer)
            {
                errors.Add(string.Format("DependencyProperty {0} is not initialized or initialized in static constructor.", propname));
            }
            else if (initializedFromKey)
            {
                var keyName = matchResults.Groups["keyName"].Value;
                var expectedKeyName = propname + "Key";
                if (keyName != expectedKeyName)
                    errors.Add(string.Format("DependencyProperty {0} either named or initialized incorrectly (key name is '{1}', expected '{2}')", propname, keyName, expectedKeyName));
            }
            else
            {
                var stringPropname = matchResults.Groups["stringPropname"].Value;
                var expected = stringPropname + "Property";
                if (propname != expected)
                    errors.Add(string.Format("DependencyProperty {0} either named or initialized incorrectly (param is '{1}', name should be {2})", propname, stringPropname, expected));
            }

            matchResults = matchResults.NextMatch();
        }
    }

    private static void CheckDependencyPropertyKeys(string sourceText, List<string> errors)
    {
        Match matchResults = PropertyKeyPattern.Match(sourceText);
        while (matchResults.Success)
        {
            var keyname = matchResults.Groups["propname"].Value;
            var modifiers = matchResults.Groups["modifiers"].Value;
            bool isPublic = matchResults.Groups["publicity"].Success;
            bool noInitializer = matchResults.Groups["noInitializer"].Success;
            bool isStatic = modifiers.Contains("static");
            bool isReadonly = modifiers.Contains("readonly");

            if (isPublic)
                errors.Add(string.Format("DependencyPropertyKey {0} is marked as public. Either make it more restricted or consider making property read-write.", keyname));
            if (!isStatic)
                errors.Add(string.Format("DependencyPropertyKey {0} is not marked as static", keyname));
            if (!isReadonly)
                errors.Add(string.Format("DependencyPropertyKey {0} is not marked as readonly", keyname));

            // Initialization in static constructor should be avoided because of performance impact of static ctor presence
            // See here: http://stackoverflow.com/questions/2921828/static-constructors-cause-a-performance-over-head
            // Also SourceChecker can't check such initialization reliably (for example with partial classes static ctor 
            // could be in other file) and ensure that property name matches string given as parameter
            if (noInitializer)
            {
                errors.Add(string.Format("DependencyPropertyKey {0} is not initialized or initialized in static constructor.", keyname));
            }
            else
            {
                var stringPropname = matchResults.Groups["stringPropname"].Value;

                var expected = stringPropname + "PropertyKey";
                if (keyname != expected)
                    errors.Add(string.Format("DependencyPropertyKey {0} either named or initialized incorrectly (param is '{1}', name should be {2})", keyname, stringPropname, expected));
            }

            matchResults = matchResults.NextMatch();
        }
    }
}

10/08/2011

WPF: Using commands with CommandParameter without CommandManager

Filed under: wpf — Ivan Danilov @ 15:33

Almost always business commands are implemented without RoutedCommand usage. There’re good reasons: business commands are not ‘application-wide’ in general. It is precise action that should be done when user clicked a button, tapped a list or something alike. So, common approach is to implement ICommand interface and CommandManager for CanExecuteChanged event implementation like below:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

Well, this approach has its downsides.

First, CommandManager knows only about the UI. If you have some external source of information, e.g. direct network connection or something alike, – you should be able to tell command ‘Your state changed! Raise your event!’ manually. It can be done with CommandManager.InvalidateRequerySuggested() method, but with updating of all commands in your app! Which sometimes is somewhat slower than required.

CommandManager is leaky in .NET 3.5. In .NET 4.0 some problems were fixed, but still there’s some criticism about it as a design concept. One could introduce memory leak and don’t notice it at all. Especially in the presence of this problem in data binding. I have also some examples that led to long-and-painful debug sessions but unfortunately can’t disclose them for legal reasons. And it would be too much work to rewrite some part just to make a demo…

At last I’m very suspicious about any static global thing that many pieces in the application subscribed to without strict control and review. WeakReference is harder to understand than normal, strong reference; delegate is harder than reference and WeakDelegate is the hardest of all.

But if you implement CanExecuteChanged event in other way – you have a problem. Many classes relies on the fact that you’re using CommandManager. It was stated in the criticism referenced above btw. You want an example? No problem. Lets take probably the most used class in WPF: Button. It assumes that if Binding changed – CommandManager would re-query commands’ statuses without additional actions. And so, if you have CommandParameter bound to some source and command not subscribed to CommandManager – this command will not be re-queried. It seems very natural for me to assume command status could have changed if parameter is changed. Even if parameter is not bound. But command relies on CommandManager. WTF?!

Well, there’s a solution for the problem. Button and other inheritors of ButtonBase doesn’t override property metadata for CommandParameter dependency property. It is our chance… 🙂

Here I present my implementation of the ICommand interface implementation:

public class GenericRelayCommand<T> : GenericRelayCommand
{
    public GenericRelayCommand(Action<T> execute)
        : base(o => execute((T) o))
    {
    }

    public GenericRelayCommand(Action<T> execute, Func<T, bool> canExecute)
        : base(o => execute((T) o), o => canExecute((T) o))
    {
    }
}

public class GenericRelayCommand : ICommand
{
    static GenericRelayCommand()
    {
        ButtonBase.CommandParameterProperty.OverrideMetadata(typeof(Button), new FrameworkPropertyMetadata(null, CommandParameterChangedCallback));
        ButtonBase.CommandParameterProperty.OverrideMetadata(typeof(DataGridColumnHeader), new FrameworkPropertyMetadata(null, CommandParameterChangedCallback));
        ButtonBase.CommandParameterProperty.OverrideMetadata(typeof(DataGridRowHeader), new FrameworkPropertyMetadata(null, CommandParameterChangedCallback));
        ButtonBase.CommandParameterProperty.OverrideMetadata(typeof(CalendarButton), new FrameworkPropertyMetadata(null, CommandParameterChangedCallback));
        ButtonBase.CommandParameterProperty.OverrideMetadata(typeof(CalendarDayButton), new FrameworkPropertyMetadata(null, CommandParameterChangedCallback));
    }

    private static void CommandParameterChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var command = d.GetValue(ButtonBase.CommandProperty) as GenericRelayCommand;
        if (command != null)
            command.RaiseCanExecuteChanged();
    }

    private readonly Func<object, bool> _canExecute;
    private readonly Action<object> _execute;

    public GenericRelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    public GenericRelayCommand(Action<object> execute, Func<object, bool> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public event EventHandler CanExecuteChanged = delegate { };

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }
}

Some generic syntax sugar is for free. Most interesting lines are in static constructor (lines 18-22) and in changing handler method (lines 25-30).

Note that despite code works, this code is not a recommended approach. Moreover it is recommended to avoid this practice:

Calls to OverrideMetadata must be performed within the static constructors of the type that provides itself as the forType parameter of OverrideMetadata. If you attempt to change metadata once instances of the owner type exist, this will not raise exceptions, but will result in inconsistent behaviors in the property system. Also, metadata can only be overridden once per type. Subsequent attempts to override metadata on the same type will raise an exception.

Nevertheless I’ve decided to stick with this approach now because in .NET 3.5 and .NET 4.0 these properties are not overridden and I hope it will be so in next version. Or (even better) this problem will be fixed.

Maybe it would be better (at least safer for sure) to subclass Button and use my own button with overridden metadata safely… but my feelings are bad about inventing the wheel. Even if it is subclassing the wheel.

15/05/2011

BooleanToVisibilityConverter

Filed under: wpf — Ivan Danilov @ 16:22

Well, it’s a shame for me but until today I wasn’t aware of BooleanToVisibilityConverter existence in the WPF library. And wrote custom classes with almost the same code again and again.

This class supports two way conversion and could handle bool and Nullable<bool> as its input.

Hope this will save time for someone who like me tries to invent a wheel again 🙂

11/05/2011

Missing WPF menu items in Visual Studio

Filed under: VisualStudio, wpf — Ivan Danilov @ 12:21

Probably you as me often were confused by the fact that some useful menu items are absent in the Add New Item in Visual Studio when you are working with Class Library.

When adding item into WPF Application you have this menu:

But with Class Library you have only this:

It turns out that you should be adding not Class Library if you want to work with WPF features but rather WPF Custom Control Library project. And then you will have all you need. I find it myself while reading Karl Shifflett’s article. Thanks, Karl! 🙂

Everything is great. Except the fact that you could already have Class Library with hundreds files inside. What should you do in this case? Replacing project and adding all your files again not seems like a good idea. So lets find out what is the difference between the project files from Visual Studio’s point of view.

I’ve created new solution, added there WPF Custom Control Library and plain old Class Library. The diff between the WpfControlLibrary1.csproj and ClassLibrary1.csproj you could see below:

The interesting point is highlighted. Its the only significant difference. In order to have XAML-related menu items in your project you have to paste this line to your *.csproj file:

<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

Enjoy!

Create a free website or blog at WordPress.com.