UXGridView Part 5: Using Custom Editing Controls
In the previous post, I’ve covered the basics of data validation and editing using UXGridView the MVVM-way. In this post, I will show you how to extend UXGridView’s editing experiences by customizing the available column types, the editing template and the editing template selector.
Defining Columns Manually
First of all, you need to set the AutoGenerateColumns property of the UXGridView control to false.
1 2 |
<Intersoft:UXGridView AutoGenerateColumns="False"> </Intersoft:UXGridView> |
Next, you specify each column manually as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<Intersoft:UXGridView AutoGenerateColumns="True"> <Intersoft:UXGridView.Columns> <Intersoft:UXGridViewCheckBoxColumn Header="Discontinued" Binding="{Binding Discontinued}"/> <Intersoft:UXGridViewComboBoxColumn Header="Category ID" Width="120" DisplayMemberPath="CategoryName" ValueMemberPath="CategoryID" Binding="{Binding CategoryID}" ValueListSource="{Binding Categories, Source={StaticResource CategoriesViewModel}}"/> <Intersoft:UXGridViewTextColumn Header="Product ID" Binding="{Binding ProductID}" IsReadOnly="True"/> <Intersoft:UXGridViewTextColumn Header="Product Name" Binding="{Binding ProductName}"/> <Intersoft:UXGridViewTextColumn Header="Units In Stock" Binding="{Binding UnitsInStock}"/> <Intersoft:UXGridViewTextColumn Header="Unit Price" Binding="{Binding UnitPrice}"/> <Intersoft:UXGridViewTextColumn Header="Units On Order" Binding="{Binding UnitsOnOrder}"/> <Intersoft:UXGridViewTextColumn Header="Quantity Per Unit" Binding="{Binding QuantityPerUnit}"/> </Intersoft:UXGridView.Columns> </Intersoft:UXGridView> |
The results look like the following screenshot.
Notice that I used three different types of column.
- UXGridViewTextColumn
The column has a textual representation for data display and a UXTextBox for data editing control.
- UXGridViewCheckBoxColumn
The column has a check box representation to display the data and a UXCheckBox for data editing control.
- UXGridViewComboBoxColumn
The column has a textual representation to display the data, a dropdown button to display the data list, and a UXComboBox for data editing control.
Using UXGridViewTextColumn and UXGridViewCheckBoxColumn is pretty straightforward, you just need to set the Binding and Header properties, and you’re all set. For UXGridViewComboBoxColumn, you need to specify the ValueListSource which is required for the combo box data source, along with the DisplayMemberPath and ValueMemberPath.
In this sample, I assigned the ValueListSource for the UXGridViewComboBoxColumn from a static resource.
1 2 3 |
<Grid.Resources> <ViewModels:CategoriesViewModel x:Key="CategoriesViewModel"/> </Grid.Resources> |
The Categories ViewModel looks like the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
using System.Collections.Specialized; using Intersoft.Client.Data.ComponentModel; using UXGridView.Samples.ModelServices; namespace UXGridView.Samples.ViewModels { public class CategoriesViewModel : ViewModelBase { public CategoriesViewModel() { this.CategoriesSource = CategoriesRepository.Instance; this.LoadCategories(); } private INotifyCollectionChanged _Categories; public INotifyCollectionChanged Categories { get { return this._Categories; } set { if (this._Categories != value) { this._Categories = value; this.OnPropertyChanged("Categories"); } } } public IDataRepository CategoriesSource { get; set; } public virtual void LoadCategories() { this.CategoriesSource.GetData ( (Categories) => { this.Categories = new PagedCollectionView(Categories); }, (error) => { } ); } } } |
Notice that the CategoriesViewModel simply retrieves the data from the CategoriesSource which used repository pattern for loosely-coupled data access. To learn more about data repository pattern, see the ProductsRepository example in my previous blog post.
Using Custom Editing Controls
In many business scenarios, you’re often asked to provide more advanced editing controls in the GridView rather than just a plain textbox, such as DateTimePicker, Slider, MaskedInput, etc. Luckily, it’s fairly easy to implement in UXGridView, thanks to the solid editing architecture. All you need to do is simply creating a data template that contains the input control of your choice, and assign it to the CellEditingTemplate property of the UXGridView.
The following examples show how to customize the editing control of each column through the provided CellEditingTemplate property.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<Intersoft:UXGridViewTextColumn Header="Units In Stock" Binding="{Binding UnitsInStock}"> <Intersoft:UXGridViewTextColumn.CellEditingTemplate> <DataTemplate> <<strong>Intersoft:UXNumericUpDown</strong> Maximum="9999" Value="{Binding UnitsInStock, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </DataTemplate> </Intersoft:UXGridViewTextColumn.CellEditingTemplate> </Intersoft:UXGridViewTextColumn><br /> <br /><Intersoft:UXGridViewTextColumn Header="Unit Price" Binding="{Binding UnitPrice}"> <Intersoft:UXGridViewTextColumn.CellEditingTemplate> <DataTemplate> <<strong>Intersoft:UXCurrencyEditor</strong> EditMask="c2" UseEditMaskAsDisplayMask="True" Value="{Binding UnitPrice, Mode=TwoWay}"/> </DataTemplate> </Intersoft:UXGridViewTextColumn.CellEditingTemplate> </Intersoft:UXGridViewTextColumn><br /> <Intersoft:UXGridViewTextColumn Header="Units On Order" Binding="{Binding UnitsOnOrder}"> <Intersoft:UXGridViewTextColumn.CellEditingTemplate> <DataTemplate> <<strong>Intersoft:UXSliderBar</strong> Value="{Binding UnitsOnOrder, Mode=TwoWay}" SmallChange="10" LargeChange="20" Maximum="100"/> </DataTemplate> </Intersoft:UXGridViewTextColumn.CellEditingTemplate> </Intersoft:UXGridViewTextColumn> |
The following examples show how to use UXDateTimePicker to edit a date time column. Notice that you can bind the BirthDate to the column and directly specify the string format in the binding expression.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<Intersoft:UXGridViewTextColumn Header="Birth Date" Binding="{Binding BirthDate, StringFormat=MM/dd/yyyy}"> <Intersoft:UXGridViewTextColumn.CellEditingTemplate> <DataTemplate> <Grid Background="White" Margin="1"> <Intersoft:UXDateTimePicker Value="{Binding BirthDate, Mode=TwoWay}" EditMask="MM/dd/yyyy" BorderThickness="0" UseEditMaskAsDisplayMask="True" VerticalAlignment="Center" HorizontalAlignment="Stretch"/> </Grid> </DataTemplate> </Intersoft:UXGridViewTextColumn.CellEditingTemplate> </Intersoft:UXGridViewTextColumn><br /> <Intersoft:UXGridViewTemplateColumn Header="Address" Binding="{Binding Address}" Width="100"> <Intersoft:UXGridViewTemplateColumn.CellTemplate> <DataTemplate> <TextBlock TextWrapping="Wrap" Text="{Binding Address}" Margin="4"/> </DataTemplate> </Intersoft:UXGridViewTemplateColumn.CellTemplate> <Intersoft:UXGridViewTemplateColumn.CellEditingTemplate> <DataTemplate> <Intersoft:UXTextBox AcceptsReturn="True" TextWrapping="Wrap" Text="{Binding Address, Mode=TwoWay}"/> </DataTemplate> </Intersoft:UXGridViewTemplateColumn.CellEditingTemplate> </Intersoft:UXGridViewTemplateColumn> |
As seen in the example above, UXGridView provides a template column named UXGridViewTemplateColumn. This column allows you to change both display and editing appearance. In the example, the UXGridViewTemplateColumn uses a wrapable TextBlock for the display, and a multi-line TextBox for data editing.
You can define literally any kind of input controls that support MVVM in the CellEditingTemplate, including our latest advanced input controls such as UXCalendar, UXDomainUpDown, UXDateTimeEditor, and so forth.
Using Cell Editing Template Selector
A rather unique scenario is where the users would like to have different editing control for the same column which depends on the data being edited. This can be achieved elegantly in UXGridView by using CellEditingTemplateSelector. It works similar to any other template selectors, so the first thing you need to do is creating a template selector class that derived from DataTemplateSelector.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
using System.Windows; using Intersoft.Client.Framework; using Intersoft.Client.UI.Data; namespace UXGridView.Samples.Selectors { public class CellEditingSelector: DataTemplateSelector { public DataTemplate NumericEditor { get; set; } public DataTemplate SliderEditor { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { UXGridViewCell cell = container as UXGridViewCell; UXGridViewRowBase rowBase = cell.OwningRowBase; UXGridViewRow row = rowBase as UXGridViewRow; switch (cell.OwningColumn.PropertyName) { case "UnitsInStock": if (rowBase.IsNewRow || (row != null && row.Index % 2 != 0)) return this.SliderEditor; else return this.NumericEditor; } return null; } } } |
The above code basically selects the editing control differently depending on whether the row is a normal or an alternating row. Notice that the conditioning is scoped to UnitsInStock column only.
Finally, let’s assign the template selector to the UXGridView, see the code below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<Grid.Resources> <DataTemplate x:Key="NumericEditor"> <Intersoft:UXNumericUpDown Maximum="100" Value="{Binding UnitsInStock, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </DataTemplate> <DataTemplate x:Key="SliderEditor"> <Intersoft:UXSliderBar Value="{Binding UnitsInStock, Mode=TwoWay}" SmallChange="10" LargeChange="20" Maximum="100"/> </DataTemplate><br /> <strong> <Selectors:CellEditingSelector x:Key="CellEditingSelector" NumericEditor="{StaticResource NumericEditor}" SliderEditor="{StaticResource SliderEditor}"/></strong> </Grid.Resources> <Intersoft:UXGridView <strong>CellEditingTemplateSelector= "{StaticResource CellEditingSelector}"</strong>> |
As the result, editing the cells of UnitsInStock for the normal row will show a UXNumericUpDown control. See the illustration below.
While editing the cells for the alternating row of the same column will show a UXSliderBar control instead.
That’s all for now, I hope this post gives you some cool ideas on using the available column types and customizing the editing controls in UXGridView. All samples I used in this blog post are available in our latest CTP release. Click here to download it now and get yourself familiar with the MVVM implementation in the UXGridView, starting from the data retrieval, handling the data editing, to customizing editing controls.
Best Regards,
Andry
Andry,
I’m evaluating your ClientUI controls now and am trying to do something similar. I’m having some challenges. Is there a working sample of this post? Is there someone I can contact?
Dear Steve,
Thanks for your interest in ClientUI controls. Yes, we have officially released UXGridView, you can download the setup at http://www.clientui.com/download. After installation, head to Intersoft WebUI Studio program group, expand Silverlight 4 group, and locate the UXGridView Samples under the Development Solutions group.
You can post your questions to http://www.intersoftpt.com/Community/ClientUI. For pre-sales questions, reach us at sales@intersoftpt.com. Thanks!
Best,
Jimmy