WPF Data Grid - Virtual Source Enhancements

WPF Team Blog
28 April 2020

The DevExpress WPF Data Grid v20.1 ships with important enhancements to virtual data source support.

To demonstrate data editing related enhancements, we recently published the following YouTube video.

You can download the PDF script for the video from this URL: WPF Data Grid - Virtual Data Source Editing

Data Editing

Your users can now edit data at the row level. They should modify row values and press Update to post changes to the underlying data source.

To enable data editing:

  1. Set the AllowEditing property to true for editable columns. 
  2. Enable Edit Entire Row mode. 
  3. Handle the ValidateRow event and save the changes to your underlying data source (database). To save changes asynchronously, set the e.UpdateRowResult property to a task that saves changes.
<dxg:GridControl x:Name="grid">
    <dxg:GridControl.Columns>
        <dxg:GridColumn FieldName="Subject" IsSmart="True" AllowEditing="true"/>
        <dxg:GridColumn FieldName="User" IsSmart="True" AllowEditing="true"/>
        <dxg:GridColumn FieldName="Created" IsSmart="True" AllowEditing="true"/>
        <dxg:GridColumn FieldName="Votes" IsSmart="True" AllowEditing="true"/>
        <dxg:GridColumn FieldName="Priority" IsSmart="True" AllowEditing="true"/>
    </dxg:GridControl.Columns>
    <dxg:GridControl.View>
        <dxg:TableView ValidateRow="TableView_ValidateRow" 
                       ShowUpdateRowButtons="OnCellValueChange" />
    </dxg:GridControl.View>
</dxg:GridControl>
private void TableView_ValidateRow(object sender, GridRowValidationEventArgs e) {
    e.UpdateRowResult = Task.Run(() => {
        IssuesService.UpdateRow(e.Row as IssueData);
    });
} 

To learn more, please explore our Enable Editing demo. If you are reading this post on a machine that includes our most recent WPF distribution (v20.1x), please follow this link to start the demo.

Partial Reload

If you used virtual sources in the past, you know that they include full row reload support. You can call the RefreshRows method or press F5 at runtime to execute a reload.

With v20.1, we extended the capabilities of this operation. You can now reload a subset of grid data instead.

Call the ReloadRows method with an array of key values that identify the rows you want to reload. ReloadRows raises the FetchRows event wherein you can process passed keys.

The following code reloads selected rows.

private void Button_Click(object sender, RoutedEventArgs e) {
    int[] selectedRowIds = 
    	grid.SelectedItems.Cast<IssueData>().Select(x => x.Id).ToArray();
    ((InfiniteAsyncSource)(grid.ItemsSource)).ReloadRows(selectedRowIds);
}

static async Task<FetchRowsResult> FetchRowsAsync(FetchRowsAsyncEventArgs e) {
    if(e.Keys != null) {
        var reloadedIssues = 
        	await IssuesService.GetIssuesById(e.Keys.Cast<int>().ToArray());
        return new FetchRowsResult(reloadedIssues);
    }
    // ...
}

Retain Selected Row and Scroll Position after Refresh

Our WPF Data Grid now retains selected row and scroll position information after refresh. Use the Take property in the FetchRows event handler to obtain row count within and above the viewport. Pass this number to your data source to return rows to a result set.

static async Task<FetchRowsResult> FetchRowsAsync(FetchRowsAsyncEventArgs e) {
    var take = e.Take ?? 30;
    var issues = await IssuesService.GetIssuesAsync(
        skip: e.Skip,
        take: take);
    return new FetchRowsResult(issues, hasMoreRows: issues.Length == take);
}

Custom Summaries

Virtual sources now allow you to process custom summaries and display them within the WPF Data Grid.

To display summaries, handle the GetTotalSummaries event. In the event handler, obtain summaries from the data source and process the e.Summaries property to return summary information to the Data Grid.

static async Task<object[]> GetTotalSummariesAsync(GetSummariesAsyncEventArgs e) {
    IssueFilter filter = MakeIssueFilter(e.Filter);
    var summaryValues = await IssuesService.GetSummariesAsync(filter);
    return e.Summaries.Select(x => {
        if(x.SummaryType == SummaryType.Count)
            return (object)summaryValues.Count;
        if(x.SummaryType == SummaryType.Max && x.PropertyName == "Created")
            return summaryValues.LastCreated;

        // Custom Summaries
        if(x.SummaryType == SummaryType.Custom && x.PropertyName == "Votes") {
            var tag = x.Tag as string;
            if(tag == "Median")
                return summaryValues.VotesMedian;
            if(tag == "StdDev")
                return summaryValues.VotesStdDev;
        }
        throw new InvalidOperationException();
    }).ToArray();
}

Specify the TotalSummary property to display summaries in the Data Grid.

<dxg:GridControl.TotalSummary>
    <dxg:GridSummaryItem SummaryType="Count" Alignment="Right"/>
    <dxg:GridSummaryItem SummaryType="Max" FieldName="Created" 
                         DisplayFormat="{}Last created: {0}" Alignment="Right"/>
    <!-- Custom Summaries -->
    <dxg:GridSummaryItem SummaryType="Custom" Tag="StdDev" FieldName="Votes" 
                         DisplayFormat="{}Votes StdDev={0}" Alignment="Right"/>
    <dxg:GridSummaryItem SummaryType="Custom" Tag="Median" FieldName="Votes" 
                         DisplayFormat="{}Votes Median={0}" Alignment="Right"/>
</dxg:GridControl.TotalSummary> 

As always, we welcome any feedback. Feel free to post comments below, or contact us via the DevExpress Support Center.

Showcase Your Apps on DevExpress.com

Highlight your business app and share your development experiences with the DevExpress community. To include your app in our upcoming App Showcase, please forward an application screenshot to clientservices@devexpress.com and tell us which DevExpress products you currently use within your organization.
No Comments

Please login or register to post comments.