Introduction
In a business app grid, you often need the ability the select multiple rows and apply an action on the selected rows.
Wouldn’t it be great if we could inject this via following “one-liner”;
ObservableCollection<Product> SelectedProducts =
new
ObservableCollection<Product>();
partial
void
EditableProductsGrid1_InitializeDataWorkspace(List<IDataService> saveChangesTo)
{
this
.FindControl(
"grid"
).AddCheckBoxColumnForMultiSelection<Product>(SelectedProducts);
}
|
The line that really matters is the extension method “AddCheckBoxColumnForMultiSelection”. It takes at input an ObservableCollection which will hold the selected items.
As you can see, there is a button called “Do Something With Selection”. We can tweak also the CanExecute behavior as follows:
1
2
3
4
5
6
7
8
9
10
11
12
|
partial
void
DoSomethingWithSelection_Execute()
{
foreach (
var
item
in
SelectedProducts)
{
this
.ShowMessageBox(item.ProductName);
}
}
partial
void
DoSomethingWithSelection_CanExecute(ref bool result)
{
result =
this
.Products.SelectedItem !=
null
&& SelectedProducts.Count >=
1
; ;
}
|
This will make sure the button is not clickable if there are no checkboxes checked.
What’s our base infrastructure for doing this?
That’s a bit more involved. But it doesn’t matter, since it’s implemented as an extension method, the whole functionality becomes a … one liner.
using
Microsoft.LightSwitch;
using
Microsoft.LightSwitch.Client;
using
Microsoft.LightSwitch.Presentation;
using
System;
using
System.Linq;
using
System.Collections.ObjectModel;
using
System.Net;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Documents;
using
System.Windows.Ink;
using
System.Windows.Input;
using
System.Windows.Markup;
using
System.Windows.Media;
using
System.Windows.Media.Animation;
using
System.Windows.Shapes;
using
Microsoft.LightSwitch.Framework.Client;
using
Microsoft.LightSwitch.Presentation.Extensions;
using
System.Diagnostics;
using
Microsoft.LightSwitch.Presentation.Implementation;
using
System.Collections.Generic;
namespace
LightSwitchApplication
{
public
static
class
MultiSelectGridExtensions
{
public
static
void
AddCheckBoxColumnForMultiSelection<T>(
this
IContentItemProxy gridProxy, ObservableCollection<T> selectedItems) where T :
class
,IEntityObject
{
EventHandler<ControlAvailableEventArgs> gridProxy_ControlAvailable =
null
;
gridProxy_ControlAvailable = (s1, e1) =>
{
DataGrid dataGrid = e1.Control
as
DataGrid;
var contentItem = dataGrid.DataContext
as
IContentItem;
var visualCollection = (contentItem.Value)
as
IVisualCollection;
dataGrid.LoadingRow +=
new
EventHandler<DataGridRowEventArgs>((s2, e2) =>
{
DataGridColumn column = dataGrid.Columns[0];
var checkBox = column.GetCellContent(e2.Row)
as
CheckBox;
T currentRowItem = e2.Row.DataContext
as
T;
if
(currentRowItem !=
null
)
{
checkBox.IsChecked = selectedItems.Contains(currentRowItem);
}
RoutedEventHandler checkboxClick =
null
;
checkboxClick = (
(s3, e3) =>
{
var selectedItem = dataGrid.SelectedItem
as
T;
if
(selectedItem ==
null
)
{
return
;
}
if
(checkBox.IsChecked ??
false
)
{
if
(!selectedItems.Contains(selectedItem))
{
selectedItems.Add(selectedItem);
}
}
else
{
selectedItems.Remove(selectedItem);
}
TriggerCanExecute(visualCollection);
});
checkBox.Click += checkboxClick;
});
var col =
new
DataGridTemplateColumn();
var xaml =
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
<CheckBox/>
</DataTemplate>"
;
var dataTemplate = XamlReader.Load(xaml)
as
DataTemplate;
col.CellTemplate = dataTemplate;
dataGrid.Columns.Insert(0, col);
gridProxy.ControlAvailable -= gridProxy_ControlAvailable;
};
gridProxy.ControlAvailable += gridProxy_ControlAvailable;
}
private
static
void
TriggerCanExecute(IVisualCollection visualCollection)
{
//this will make sure that the CanExecute method is triggered in a potential button for doing something
//with the selection result.
//not elegant, but no other option...
var currentItem = visualCollection.SelectedItem;
var collection = visualCollection
as
IEnumerable<IEntityObject>;
if
(!visualCollection.SelectedItem.Equals(collection.Last()))
{
visualCollection.SelectedItem = collection.Last();
}
else
{
visualCollection.SelectedItem = collection.First();
}
visualCollection.SelectedItem = currentItem;
}
}
}
|
Can I download it?
No, you can’t because I stopped uploading samples, as from today. Full stop.
But, … you can directly inject the functionality with NuGet into the silverlight client project. (at least when you use the latest LightSwitch version)