I want to repurpose the new item row to allow vertical editing of the grid, i.e. an edit in any cell of the new item row will be propagated down that column and the new item row's cell will be cleared after propagation to the other records.
- How can I keep the new item row in an editable state, removing the need to click the 'click here to add new item' placeholder
- Which events can I use to stop the new row addition, it seems I have to allow the addition then remove the row
- It would be nice to use a behavior for this (and not have to extend the grid), my other approach below is using a behavior and hooking the DataLoaded event to add the empty row
I have tried not using the new row and just adding an empty row to the data source but it doesn't play nice with descending sorting, however, most other operations seem to work ok on the minimal testing I have done. I think the new item row might be the more robust approach though.
Thanks,
Maurice
7 Answers, 1 is accepted
Thanks for the detailed explanation of your requirement.
The control does not have a built-in mechanism that corresponds exactly to such behavior. There is, however, a possible approach for achieving your goal through the RowValidating event. It exposes the Row property through which you can access the edited element before the row edit is committed. So, you should be able to fetch the input entered by the user, make a copy of this data into a new object and insert it in the source collection. Then, you can clear the property values of the edited object and return from the RowValidating event. Returning from the event will keep the row in edit mode.
Can you please give it a try? Would such an approach meet your requirements?
Regards,
Stefan
Progress Telerik
Stefan, I will give it a try, once I have it working I will post the code in case others have such a requirement.
Regards,
Maurice
Hi Stefan,
This is not going as smoothly as I had hoped it would, I wonder if you can give me some assistance?
I have attached a sample project. The initial issues are (commented in code also):
- Call BeginEdit() on the GridViewNewRow instance breaks the insert row functionality, I have tried this from both GridView.OnDataLoaded (fires multiple times, is not always non-null) and GridView.RowLoaded (fires once, so a lot nicer).
- I can't get access to the typed data item behind the row insert in the GridView.RowValidating event to clear the data item values, although this event is not firing reliably due to issues in #1.
Edit: I cannot attach a zip, so I will paste the code here for you to create a project from.
01.
using
System.Windows.Interactivity;
02.
03.
using
Telerik.Windows.Controls;
04.
using
Telerik.Windows.Controls.GridView;
05.
06.
namespace
TelerikWpfApp1
07.
{
08.
public
class
VerticalEditBehavior : Behavior<RadGridView>
09.
{
10.
protected
override
void
OnAttached()
11.
{
12.
base
.OnAttached();
13.
14.
AssociatedObject.RowLoaded += OnRowLoaded;
15.
AssociatedObject.RowValidating += OnRowValidating;
16.
}
17.
18.
private
void
OnRowLoaded(
object
sender, RowLoadedEventArgs e)
19.
{
20.
if
(e.Row
is
GridViewNewRow row)
21.
{
22.
// this row breaks the new row funcitoanlity
23.
row.BeginEdit();
24.
}
25.
}
26.
27.
private
void
OnRowValidating(
object
sender, GridViewRowValidatingEventArgs e)
28.
{
29.
if
(e.Row
is
GridViewNewRow && e.EditOperationType == GridViewEditOperationType.Insert)
30.
{
31.
// how to access the row data item and clear its values?
32.
// the code below doesnt work as e.Row.Item is typeof(object)
33.
//foreach (var value in e.OldValues)
34.
//{
35.
// e.Row.Item.GetType().GetProperty(value.Key).SetValue(e.Row.Item, value.Value);
36.
//}
37.
38.
}
39.
}
40.
41.
protected
override
void
OnDetaching()
42.
{
43.
base
.OnDetaching();
44.
45.
AssociatedObject.RowLoaded -= OnRowLoaded;
46.
AssociatedObject.RowValidating -= OnRowValidating;
47.
}
48.
}
49.
}
01.
using
System;
02.
using
System.Collections.ObjectModel;
03.
using
System.ComponentModel.DataAnnotations;
04.
05.
using
Telerik.Windows.Controls;
06.
07.
namespace
TelerikWpfApp1
08.
{
09.
public
class
MainWindowViewModel : ViewModelBase
10.
{
11.
public
ObservableCollection<TestRow> Rows {
get
; } =
new
ObservableCollection<TestRow>()
12.
{
13.
new
TestRow { Text =
"One"
, Number = 1, Date = DateTime.Today },
14.
new
TestRow { Text =
"Two"
, Number = 2, Date = DateTime.Today },
15.
new
TestRow { Text =
"Three"
, Number = 3, Date = DateTime.Today },
16.
new
TestRow { Text =
"Four"
, Number = 4, Date = DateTime.Today },
17.
new
TestRow { Text =
"Fix"
, Number = 5, Date = DateTime.Today },
18.
new
TestRow { Text =
"Six"
, Number = 6, Date = DateTime.Today }
19.
};
20.
}
21.
22.
public
class
TestRow
23.
{
24.
public
string
Text {
get
;
set
; }
25.
26.
public
int
? Number {
get
;
set
; }
27.
28.
[DisplayFormat(DataFormatString =
"d"
)]
29.
public
DateTime? Date {
get
;
set
; }
30.
}
31.
}
01.
<
Window
x:Class
=
"TelerikWpfApp1.MainWindow"
03.
xmlns:x
=
"http://schemas.microsoft.com/winfx/2006/xaml"
04.
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
05.
xmlns:i
=
"clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
06.
xmlns:local
=
"clr-namespace:TelerikWpfApp1"
07.
Title
=
"MainWindow"
Height
=
"350"
Width
=
"525"
>
08.
09.
<
Window.DataContext
>
10.
<
local:MainWindowViewModel
/>
11.
</
Window.DataContext
>
12.
13.
<
telerik:RadGridView
Grid.Row
=
"1"
ShowGroupPanel
=
"False"
NewRowPosition
=
"Top"
AlternationCount
=
"2"
ItemsSource
=
"{Binding Rows}"
CanUserInsertRows
=
"True"
>
14.
<
i:Interaction.Behaviors
>
15.
<
local:VerticalEditBehavior
/>
16.
</
i:Interaction.Behaviors
>
17.
</
telerik:RadGridView
>
18.
</
Window
>
Regards,
Maurice
Thank you for the update.
The data item in the event handler can be accessed by using the DataContext of the Row property.
private
void
clubsGrid_RowValidating(
object
sender, GridViewRowValidatingEventArgs e)
{
if
(e.Row
is
GridViewNewRow && e.EditOperationType == GridViewEditOperationType.Insert)
{
var item = e.Row.DataContext
as
Club;
}
}
I am however, also experiencing trouble keeping the row in edit mode when inserting the new item. I am now working on providing you with a working solution. I will do my best to update you shortly.
Regards,
Stefan
Progress Telerik
I performed various approaches in my attempts to reach a working solution. Achieving such customization turned out to be not that trivial as it looked in the first place. I have attached a sample application that demonstrates an approach of using the RowEditEnded event instead. In order to keep the editing operation on the first row, I have inserted a new empty item and forced the CurrentCell of RadGridView. This would result in a second trigger of the RowEditEnded rooting from the CurrentCell, thus a check whether the previously edited item is not the same as the currently edited one has to be applied. After that, the NewRowPosition of RadGridView is set to None, so the built-in mechanism for adding a new item is available only initially.
I do understand that this solution is far from straightforward, but it is the closest one for such customization. I cannot also guarantee that it will correspond exactly to your requirements.
I hope it helps.
Regards,
Stefan
Progress Telerik
Hi Stefan,
Thank you for taking the time to look into this for me. I tried a basic attempt at using a new empty row but sorting (and I suspect other things, like filtering) in the grid becomes problematic using that approach. An MVP (without validation, default values, etc.) of what I need is below, it appears to work as expected except for the new row not being able to be programmatically put into edit mode. I will now try, either; simulating a user click on the PART_AlwaysVisibleNewRow or adjusting the styles and perhaps using triggers to hide that element and trigger an edit on the row ... somehow.
01.
private
void
clubsGrid_RowEditEnded(
object
sender, GridViewRowEditEndedEventArgs e)
02.
{
03.
if
(e.Row
is
GridViewNewRow)
04.
{
05.
clubsGrid.Items.Remove(e.EditedItem);
06.
}
07.
}
08.
09.
private
void
clubsGrid_CellEditEnded(
object
sender, GridViewCellEditEndedEventArgs e)
10.
{
11.
if
(e.Cell !=
null
&& e.Cell.ParentRow
is
GridViewNewRow)
12.
{
13.
var column = e.Cell.DataColumn.DataMemberBinding.Path.Path;
14.
var items = clubsGrid.ItemsSource
as
IEnumerable<
object
>;
15.
16.
foreach
(var item
in
items)
17.
{
18.
item.GetType().GetProperty(column).SetValue(item, e.NewData,
null
);
19.
}
20.
}
21.
}
Regards,
Maurice
Thank you for the update.
I am sorry to hear that you are still not able to achieve the desired behavior. I can confirm that a stable solution that works as expected in all scenarios would hardly be implemented and I cannot guarantee that this is even possible. Of course, if I can be of further assistance feel free to approach me.
Have a nice week, Maurice.
Regards,
Stefan
Progress Telerik