Friday, September 21, 2007

Linq with Xceed's WPF Grid - Part III - Hooking up the Delete

One of the under appreciated features of WPF is its Command support. This feature allows you to hook up events in a more abstract and loosely coupled way; with a great collection of common actions provided by default.

To hook up delete functionality from Xceed's data grid to a Linq data table, I took advantage of these Command gems and as you will see, they make things very easy to use.

The provided ApplicationCommands.Delete command, comes with a localized string ("Delete") and associated key bindings ("Del" Key).

Handling this command in the LinqGrid is as simple as calling the following in the initialization routines:

CommandBindings.Add(new CommandBinding(ApplicationCommands.Delete,
OnDeleteCommand, OnCanDeleteCommand));

Implementing the OnCanDeleteCommand to return true, if any items are selected and the OnDeleteCommand to delete the selected items, and it's done! Well almost.

Automatically deleting the selected items (with the "Del" key) without any warning is usually not the best behaviour, so I implemented a RoutedEvent called PreviewDelete, which allows you to show a message box and/or cancel the delete.

Show me the XAML

Another great benefit of using Commands is the ability to bind other UI elements as the action co-coordinator for the command. i.e Buttons, Context Menus, etc.

Not only is this clean and easy, but it also has built in routines to control the IsEnabled state. ie. Button is disabled if you cannot currently delete.

<Button Command="Delete"
CommandTarget="{Binding ElementName=users}"
Content="{Binding Command.Text, RelativeSource={RelativeSource self}}" />

The "Command" is quite simply a reference to the ApplicationCommands.Delete command, while the "CommandTarget" is the name I gave to my LinqGrid.

The unfortunately long "Content" attribute is the Buttons label, bound to the Command itself. Remember how I said the provided commands have localized names... this is how you access them in XAML. Thankfully, this is also purely optional.

This is all you need to do. When the button is pressed, the Command is fired and our LinqGrid performs the delete, first checking with PreviewDelete for its permission.

Download the sample solution for the full code.


Anonymous said...

I downloaded your code, and got it working, modified for my own needs.

It works nicely thanks.

However, it doesn't work from a detail grid, presumably because it doesn't use the subclassed grid, rather the default grid.

I wonder if there is a way to do this without repeating the subclassing process on the DetailConfiguration class (assuming that is even possible).

david.havlik said...

Hi I download this solutiuon and until I was using Xceed datagrid version 2.x.x. everything work fine. But since I update xceed datagrid to version 3.1 I have a problem. Program throw me an exception that IBindingList doesnt support removing. Does anybody know how can I fix this?
Problem is in this method:

public void DeleteSelected()
IBindingList list = ItemsSource as IBindingList ?? DataContext as IBindingList;
if (list != null && LinqContext != null)
// Use a copy, as we are modifying the SelectedItems collection
object[] selected = new object[SelectedItems.Count];
SelectedItems.CopyTo(selected, 0);
Array.ForEach(selected, i => list.Remove(i));