Actually such a feature has already been implemented. You may find additional information in this
forum thread
. Please let me know in case you have any further questions.
Unfortunately that does not solve the sorting problem. I do not have a problem with the filtering control, I have a problem with the sorting of the GridViewComboBoxColumn. The default sort works off of the DataMemberBinding unless you set the SortMemberPath, but the SortMemberPath is simply another property on the object the row is bound to. In your example the ViewModel is adding a new property called SortID and setting that for every object.
What happens if I add a new object to the collection? Now I have to loop through the entire collection and set the "SortID" property for every combo box column in the grid. Not elegant.
I am looking for a way to get the control to sort by DisplayMemberPath so I don't need to create many many seperate properties for the grids in our application.
Indeed additional setting of the SortMemberPath will be needed. In order to avoid this, you could handle the Sorting event of the RadGridView and apply your custom sorting which sorts based on the DisplayMemberPath. You can check the CustomSorting WPF Demo and our
online documentation
for an example.
As I explained in the first post I would rather not use custom sorting because I have to implement that on every GridViewComboBoxColumn in every grid inside the application, some of these columns are built dynamically as well which adds another layer of complexity. I am looking for something generic that I can reuse over and over.
Is there no way to inherit from the GridViewComboBoxColumn and write some generic code to sort? That way we simply use this new column and the application will behave as all users would expect it to behave.
Unfortunately this is what we can suggest regarding Sorting of this column. Inheriting it will not help as the sorting logic is in the Data Engine, it is not in the column.
I found out a solution, maybe it could be simplier, but for me it is good enough.
First you have to set ".IsCustomSortingEnabled = True" on the GridViewComboBoxColumn.
Then in the sorting handler:
Private
Sub
Datagr_Sorting(sender
As
Object
, e
As
GridViewSortingEventArgs)
Handles
Datagr.Sorting
Dim
CB = TryCast(e.Column, GridViewComboBoxColumn)
If
Not
CB
Is
Nothing
Then
If
e.Column.IsCustomSortingEnabled
Then
Dim
cbis = TryCast(CB.ItemsSource, DataView)
If
Not
cbis
Is
Nothing
Then
Datagr.SortDescriptors.Clear()
If
e.OldSortingState = SortingState.None
Or
e.OldSortingState = SortingState.Descending
Then
e.NewSortingState = SortingState.Ascending
ElseIf
e.OldSortingState = SortingState.Ascending
Then
e.NewSortingState = SortingState.Descending
'Else
' 'If the sorting state is descending, apply default sorting to the items.
' e.NewSortingState = SortingState.None
End
If
' create new DV
Dim
dgvDV = DGVNaturalColumnSort(CB.SelectedValueMemberPath, e.NewSortingState, CB.DisplayMemberPath, cbis)
'Set the sorted collection as source of the RadGridView
e.DataControl.ItemsSource = dgvDV
e.Cancel =
True
Exit
Sub
End
If
End
If
End
If
'All others
If
e.NewSortingState = SortingState.None
Then
e.NewSortingState = SortingState.Ascending
End
If
End
sub
Private
Function
DGVNaturalColumnSort(colName
As
String
, sortt
As
SortingState, sortName
As
String
, dbis
As
DataView)
As
DataView
Dim
NComparer
As
New
NaturalStringComparer(sortt, colName, sortName, dbis)
Dim
tempDT = datatable.DefaultView.Table.AsEnumerable().OrderBy(
Function
(s) s.Field(Of
Object
)(colName), NComparer).CopyToDataTable
Return
New
DataView(tempDT)
Catch
ex
As
Exception
Return
Nothing
End
Try
End
Function
Public
Class
NaturalStringComparer
Implements
IComparer(Of
String
)
Dim
mysortflipper
As
SortingState
Dim
mycolName
As
String
Dim
mysortName
As
String
Dim
dict
As
New
Dictionary(Of
Integer
,
String
)()
Public
Sub
New
()
End
Sub
Public
Sub
New
(sort
As
SortingState, colName
As
String
, sortName
As
String
, dbis
As
DataView)
mysortflipper = sort
mycolName = colName
mysortName = sortName
For
Each
a
In
dbis.Table.AsEnumerable
dict.Add(a.Field(Of
Object
)(colName), a.Field(Of
Object
)(sortName))
End
Sub
Public
Function
Compare(x
As
String
, y
As
String
)
As
Integer
_
Implements
IComparer(Of
String
).Compare
' convert DBNull to empty string
Dim
x1 =
If
(
String
.IsNullOrEmpty(x),
String
.Empty, dict(x))
Dim
y1 =
If
(
String
.IsNullOrEmpty(y),
String
.Empty, dict(y))
'String Compare
Select
Case
mysortflipper
Case
SortingState.Ascending
Return
String
.Compare(x1, y1)
Case
Else
Return
String
.Compare(y1, x1)
End
Select
End
Function
End
Class
Maybe you will find an eleganter solution.
Regards,
Patrick