Category Archives: WPF

DXGrid, Immediate Updates & Nested Attached Behaviours

With the Devexpress grid control, when you edit a row, it doesn’t update the view model until the row loses focus. I needed immediate update so that my view model would get notified when a checkbox in the grid was toggled as soon as it happened. So I wrote an attached behaviour to facilitate this without having to resort to code behind.

This example is also interesting as it shows how to maintain extra state on a control, using a second attached behaviour managed internally by the main one. In this case, this is necessary to manage the lifetime of the subscription to the controls events. I couldn’t find any info about this technique on the net, so not sure how well known it is.

The code is fairly well commented so should be self explanatory. You’ll also notice that the events are being converted to IObservable with Reactive extensions. I love the functional approach of reactive and the way that reactive returns an IDisposable makes the lifetime management really easy.

n.b. Since this class is dependent on Reactive Extensions, your references will need to look something like this:

image

You can grab Reactive (Rx) from nuget.

using System;
using System.Windows;
using DevExpress.Xpf.Grid;
using System.Reactive.Linq;
using System.Reactive;

namespace Utils.DevExpress
{
	/// <summary>
	/// Attached behaviour for Dev Express GridView's that forces the grid to immediately update the bound
	/// datasource row when values are changed in it. By default it will only update when the row loses
	/// focus.
	/// 
	/// Usage in xaml:
	/// 1. Add Reference
	///    xmlns:dxu="clr-namespace:Utils.DevExpress;assembly=Utils.DevExpress"
	/// 
	/// 2. Attach to GridView
	///    {dxg:TableView ShowGroupPanel="False"  MultiSelectMode="Row"
	///                   dxu:DXGridViewUpdateBehaviour.ImmediateUpdate="True"       
	///                   AllowBestFit="True" AutoWidth="True"/}
	///    {/dxg:GridControl.View}
	/// 
	/// Derived from DevExpress recommended work around which was based on code behind:
	///    http://www.devexpress.com/Support/Center/p/E2832.aspx
	/// 
	/// Author : Daniel Harman
	/// Date   : 07.09.2011
	/// </summary>

	public class DXGridViewUpdateBehaviour : DependencyObject
	{

		#region Immediate Update Attached Property

		public static bool GetImmediateUpdate(DependencyObject obj)
		{
			return (bool)obj.GetValue(ImmediateUpdateProperty);
		}

		public static void SetImmediateUpdate(DependencyObject obj, bool value)
		{
			obj.SetValue(ImmediateUpdateProperty, value);
		}

		/// Immediate update is a boolean attached DP that when set to true, will ensure that grid row updates
		/// are immediately propagated to the view model, rather than only when the row loses focus.
		public static readonly DependencyProperty ImmediateUpdateProperty = DependencyProperty.RegisterAttached(
				"ImmediateUpdate", typeof(bool), typeof(GridViewBase),
				new UIPropertyMetadata(false, OnImmediateUpdatePropertyChanged));

		#endregion

		#region Grid View Update Behaviour Subscription Attached Property

		public static DXGridViewUpdateBehaviourSubscription GetGridViewUpdateBehaviourSubscription(DependencyObject obj)
		{
			return (DXGridViewUpdateBehaviourSubscription)obj.GetValue(GridViewUpdateBehaviourProperty);
		}

		public static void SetGridViewUpdateBehaviourSubscription(
			DependencyObject obj, DXGridViewUpdateBehaviourSubscription value)
		{
			obj.SetValue(GridViewUpdateBehaviourProperty, value);
		}

		/// This property is used to store an instance of the subscription on the control. This instance
		/// contains the rxEventHandler IDisposable so that we can clean up when we want to change the binding
		/// etc.
		public static readonly DependencyProperty GridViewUpdateBehaviourProperty = DependencyProperty.RegisterAttached(
				 "GridViewUpdateBehaviour", typeof(DXGridViewUpdateBehaviourSubscription), typeof(DXGridViewUpdateBehaviour),
				 new UIPropertyMetadata(null));

		#endregion

		/// <summary>
		/// Handle changes to ImmediateUpdate.
		/// </summary>
		/// <param name="d">A child of GridViewBase</param>
		/// <param name="e">true/false for value of attached DP.</param>
		private static void OnImmediateUpdatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var gridViewBase = (GridViewBase)d;
			var oldValue = (bool)e.OldValue;
			var newValue = (bool)e.NewValue;

			if (oldValue == newValue)
				return;

			// Remove old sub if it exists.
			var oldSub = GetGridViewUpdateBehaviourSubscription(d);

			if (oldSub != null)
				oldSub.Dispose();

			// If ImmediateUpdate==true then create new sub.
			if (newValue)
				SetGridViewUpdateBehaviourSubscription(d, new DXGridViewUpdateBehaviourSubscription(gridViewBase));
		}

		/// <summary>
		/// Nested class to manage the lifetime of the reactive event handler. This is attached the GridView
		/// as an attached dependency property.
		/// </summary>
		public class DXGridViewUpdateBehaviourSubscription : IDisposable
		{
			IDisposable rxEventHandler;

			public DXGridViewUpdateBehaviourSubscription(GridViewBase gridViewBase)
			{
				// Create an rx observable of the events and subscribe handler to it.
				rxEventHandler = Observable
						 .FromEventPattern<CellValueChangedEventHandler, CellValueChangedEventArgs>(
								 h => gridViewBase.CellValueChanging += h,
								 h => gridViewBase.CellValueChanging -= h)
						 .Subscribe(OnCellValueChanging);
			}

			/// <summary>
			/// On notification that a cell value is changing, force the TableView to update the view model immediately.
			/// </summary>
			/// <param name="ep"></param>
			void OnCellValueChanging(EventPattern<CellValueChangedEventArgs> ep)
			{
				(ep.Sender as GridViewBase).PostEditor();
			}

			#region IDisposable Members

			public void Dispose()
			{
				rxEventHandler.Dispose();
			}

			#endregion
		}
	}
}

Binding a DevExpress Grid Context Menu to a MVVM ViewModel Command

One of the things I sometimes wrestle with, is keeping to MVVM when working with DevExpress controls.

Today I was trying to bind the right click context menu on their grid control, to a command on my view model. I started off working from some of their example code which was event and code behind based. This lead me to the using the EventToCommand pattern, as didn’t want any code behind.

This is where the pain began! Firstly their BarButtonItem is derived from FrameworkContentElement, not FrameworkElement, which makes it incompatible with MVVM Light. I posted a question about this on stackoveflow which was answered with a great workaround.

However before I received that answer, I had already decided to just use the more vanilla System.Windows.Interactivity InvokeCommandAction which doesn’t have the limitation of only binding to FrameworkElements.

Again I ran into problems. It seems that the context menu’s from dev express are in their own visual tree, so I tried all sorts of bindings to try and get back to my ViewModel. None of which worked!

It was at this point that my colleague pointed out that, the menu items are actually buttons and have a command property. So all this wrestling with triggers was a complete waste of time – curses!

However, the binding to get back to the ViewModel is not at all obvious, as the DataContext on these popup menus is not what you might expect. Anyway it is possible, and the way to do it is as follows:

<dxg:TableView.RowCellMenuCustomizations>
    <dxb:BarButtonItem Name="deleteRowItem" Content="Delete"
        Command="{Binding View.DataContext.DeleteCommand}" />
</dxg:TableView.RowCellMenuCustomizations>

Binding WPF Events to MVVM ViewModel Commands

This article looks at binding event on WPF controls to commands in your MVVM view model.

A lot of MVVM examples show you how to bind a command in a view to an ICommand in your view model. What they sometimes skirt over, is how you get events into the view model. Prism for example recommends the use of an Event Aggregator.

However, there is an easier way! All we need is a class library that is part of Expression Blend. It’s called System.Windows.Interactivity and you can get hold of it from a variety of sources, but the one I recommend is the MVVM Light library.

This gives you the ability to create a trigger on an event and bind it to an ICommand on the view model.

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter" >
            <i:InvokeCommandAction Command="{Binding FooCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

Assuming the DataContext is your view model, then the above will map the ‘MouseEnter’ event to ‘FooCommand’ on the view model.

The only issue here, is that InvokeCommandAction doesn’t give you the event parameters.

I’ve already mentioned MVVM Light, and this library provides the a solution, by offering a different event to command behaviour that can optionally pass the parameters. Like this:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter" >
             <cmd:EventToCommand Command="{Binding FooCommand}"
                 PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

With this, you’ll find the MouseEventArgs in the Object passed into your command.

ReactiveUI Property Name to Field Mapping Convention Override

In a previous post I described how you can use the ReactiveUI framework to bind properties to both INotifyPropertyChanged and make them Observable to Reactive Extensions (Rx).

The default binding behaviour of the RaiseAndSetIfChanged helper is to assume that a property named “MyProperty” has a backing field called “_MyProperty”. This is not a common convention, and whilst you can explicitly override this behaviour in RaiseAndSetIfChanged, it’s extra work.

Fortunately, the framework offers a way of modifying the default mapping behaviour by binding a different function to RxApp.GetFieldNameForPropertyNameFunc.

Here are a couple of example functions that implement alternative behaviours. The first of which maps to _propertyName and the latter, simply topropertyName.

                /// Maps property name MyProperty to field name _myProperty.
                Func<string, string> UnderscoreFirstToLowerBehaviour = x =>
                {
                        char[] arr = x.ToCharArray();
                        arr[0] = char.ToLower(arr[0]);
                        return '_' + new String(arr);
                };

                /// Maps property name MyProperty to field name myProperty.
                Func<string, string> FirstToLowerBehaviour = x =>
                {
                        char[] arr = x.ToCharArray();
                        arr[0] = char.ToLower(arr[0]);
                        return new String(arr);
                };

To use one of these behaviours, all you need do is call the following once during app startup:

RxApp.GetFieldNameForPropertyNameFunc = underscoreFirstToLowerBehaviour;

Given this is executed on each notification, I guess the second coding style is more optimal!

p.s. I’m not sure these are the fastest implementations of these conversions, and I’m not going to benchmark, however I did base the code on http://www.dotnetperls.com/uppercase-first-letter who did do some benchmarking on similar code.

Using ReactiveUI to Integrate INotifyPropertyChanged & IObservable

ReactiveUI offers some great helper functionality for integrating Reactive Extensions into your WPF user interfaces.

One of these is the ReactiveObject base class, which when derived from, grants your classes access to the ‘RaiseAndSetIfChanged’ helper function.

This conveniently wires up your properties to INotifyPropertyChanged/IObservable, so in one step you have a class that can be bound directly to your xaml AND observed using Rx.

	class Person : ReactiveObject
	{
		string _Name;
		public string Name
		{
			get { return Name; }
			set { this.RaiseAndSetIfChanged(x => x.Name, value); }
		}
	}

By convention ReactiveUI expects the backing field to have the same name as the property, but with an underscore prepended. So if you want a different backing field name, you have to explicitly reference it in RaiseAndSetIfChanged:

	class Person : ReactiveObject
	{
		string _name;
		public string Name
		{
			get { return _name; }
			set { this.RaiseAndSetIfChanged(x => x.Name, x=> x._name, value); }
		}
	}

The obvious question is then, ‘how do we subscribe to changes on these properties?’. The secret is to use the ReactiveObject base class function ObservableForProperty.

In the example below, we are doing something a little more complex that simply watching one property. Instead we are observing two properties containing cash amounts, and automatically updating a total when either changes.

	class Dividend : ReactiveObject
	{
		decimal _AnnouncedAmt;
		public decimal AnnouncedAmt
		{
			get { return _announcedAmt; }
			set { this.RaiseAndSetIfChanged(x => x.AnnouncedAmt, value); }
		}

		decimal _ForecastAmt;
		public decimal ForecastAmt
		{
			get { return _forecastAmt; }
			set { this.RaiseAndSetIfChanged(x => x.ForecastAmt, value); }
		}

		decimal _TotalAmt;
		public decimal TotalAmt
		{
			get { return _totalAmt; }
			set { this.RaiseAndSetIfChanged(x => x.TotalAmt, value); }
		}

		public Dividend()
		{
			Observable
				.Merge(	this.ObservableForProperty(x => x.AnnouncedAmt),
						this.ObservableForProperty(x => x.ForecastAmt))
				.Subscribe(_ =>  TotalAmt = AnnouncedAmt + ForecastAmt);
		}
	}

You’ll notice that the lambda parameter in the subscribe is an ‘_’, this is a functional programming convention for naming parameters that are not used in the lambda function.

There are a couple of advantage with this approach:

  • Clean and simple property get/set methods. The alternative implentation would either have to update the total in the setters, or even more verbosely, and unlikely in practise, listen on the INotifyPropertyChanged interface.
  • External code can also bind to changes on these properties. We’ve implemented the Observer pattern with very little code or overhead

ReactiveObject makes a great base class to derive your MVVM view models from.