Hello Raphael,
I don't see a license on your account (trial or purchased), so I cant tell what version you're using, but I will assume the latest (2018.3.1122). If you are using your employer's copy, have them assign you as the licensed user here so you can open support tickets:
Manage Licensed Users.
Okay, let me get right to the answers:
Sort Event
There's not Sort event to hook into, but you can hook into the
SortDescriptors CollectionChanged event which is effectively the same thing.
LoadOnDemand and sorting
Because you're using load on demand, the DataGrid's DataView (the internal collection that gets sorted/grouped/filtered) doesn't know about all the data. Therefore,
it can only sort what it currently has in the ItemsSource. This is the main limitation of using any type of
load on demand scenario.
Options:
1 - Remove Load On demand and use DataGrid sorting features
You can either load all the items and let the DataGrid sort them, or use load on demand and load pre-sorted data. You can't use both simultaneously.
2 - Sort the remote data and keep LoadOnDemand
One option to keep Load On Demand is to sort the original data set, usually done through the API or Database that supplies the data. Then, you reset the ItemSource, which will trigger the next fetch on the, now sort-defined, data source.
Conceptual Example of Remote Sorting
As a conceptual example, lets say the API accepts a sort parameter in the query string:
mysite.com/api/customers?startIndex=0&count=20&sort=first_name
Then when the LoadOnDemand Action is invoked, the
startIndex and
count parameters will be incremented by your app's increment logic, but each call to the API contains a sort parameter. Since the data from the API is already sorted, the DataGrid just loads the items in order.
Column Width
The trick for this is to just set a custom HeaderContentTemplate and get that element's width instead. Note that you'll need to add a few pixels to make up for the vertical ellipsis, but that always a fixed size.
Here's a simple example to show how the
custom header is set with a simple
view model property binding for the width:
<
ContentPage
...>
<
ContentPage.BindingContext
>
<
local:MainViewModel
x:Name
=
"ViewModel"
/>
</
ContentPage.BindingContext
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
/>
<
RowDefinition
Height
=
"Auto"
/>
</
Grid.RowDefinitions
>
<
telerikGrid:RadDataGrid
x:Name
=
"DataGrid"
AutoGenerateColumns
=
"False"
>
<
telerikGrid:RadDataGrid.Columns
>
<
telerikGrid:DataGridTextColumn
PropertyName
=
"Country"
HeaderText
=
"Country"
>
<
telerikGrid:DataGridTextColumn.HeaderContentTemplate
>
<
DataTemplate
>
<
Grid
Width
=
"{Binding CountryColumnWidth, Source={x:Reference ViewModel}, Mode=OneWayToSource}"
>
<
Label
Text
=
"{Binding}"
/>
</
Grid
>
</
DataTemplate
>
</
telerikGrid:DataGridTextColumn.HeaderContentTemplate
>
</
telerikGrid:DataGridTextColumn
>
<
telerikGrid:DataGridTextColumn
PropertyName
=
"Capital"
HeaderText
=
"Capital"
>
<
telerikGrid:DataGridTextColumn.HeaderContentTemplate
>
<
DataTemplate
>
<
Grid
Width
=
"{Binding CapitalColumnWidth, Source={x:Reference ViewModel}, Mode=OneWayToSource}"
>
<
Label
Text
=
"{Binding}"
/>
</
Grid
>
</
DataTemplate
>
</
telerikGrid:DataGridTextColumn.HeaderContentTemplate
>
</
telerikGrid:DataGridTextColumn
>
</
telerikGrid:RadDataGrid.Columns
>
</
telerikGrid:RadDataGrid
>
<
Grid
Grid.Row
=
"1"
HeightRequest
=
"50"
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
=
"{Binding CountryColumnWidth, Source={x:Reference ViewModel}, Mode=OneWay}"
/>
<
ColumnDefinition
Width
=
"{Binding CapitalColumnWidth, Source={x:Reference ViewModel}, Mode=OneWay}"
/>
<
ColumnDefinition
Width
=
"*"
/>
</
Grid.ColumnDefinitions
>
<
Grid
BackgroundColor
=
"Red"
/>
<
Grid
BackgroundColor
=
"Green"
Grid.Column
=
"1"
/>
<
Grid
BackgroundColor
=
"Blue"
Grid.Column
=
"2"
/>
</
Grid
>
</
Grid
>
</
ContentPage
>
public
partial
class
MainPage : ContentPage
{
public
MainPage()
{
InitializeComponent();
DataGrid.ItemsSource =
new
List<Data>
{
new
Data { Country =
"India"
, Capital =
"New Delhi"
},
new
Data { Country =
"South Africa"
, Capital =
"Cape Town"
},
new
Data { Country =
"Nigeria"
, Capital =
"Abuja"
},
new
Data { Country =
"Singapore"
, Capital =
"Singapore"
}
};
DataGrid.SortDescriptors.CollectionChanged += SortDescriptors_CollectionChanged;
}
private
void
SortDescriptors_CollectionChanged(
object
sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Debug.WriteLine($
"SortDescriptorsChanged: {DataGrid.SortDescriptors?.Count}"
);
}
}
public
class
Data
{
public
string
Country {
get
;
set
; }
public
string
Capital {
get
;
set
; }
}
public
class
MainViewModel : BindableBase
{
private
double
_countryColumnWidth;
private
double
_capitalColumnWidth;
public
double
CountryColumnWidth
{
// The only thing calling this getter is the extra Grid control, so we can add the additional pixels
// for the column options vertical ellipsis
get
=> _countryColumnWidth + 40;
// The only thing calling the setter is the custom HeaderContentTemplate element
set
=> SetProperty(
ref
_countryColumnWidth, value);
}
public
double
CapitalColumnWidth
{
get
=> _capitalColumnWidth;
set
=> SetProperty(
ref
_capitalColumnWidth, value);
}
}
Here is the result at runtime:
Sum
Your final question about calculating the sum to place in the footer area will also need to be done manually, but this is an easy LINQ methods to call.
Let's say in the previous example had a Population column instead of a Capital column, you can
get the SUM for a column and set some
Label Text value like this
Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans?
Do you want to know when a feature you care about is added or when a bug fixed?
Explore the
Telerik Feedback Portal
and vote to affect the priority of the items