Back to Devexpress

Bind to Virtual Sources

wpf-403918-controls-and-libraries-data-grid-bind-to-data-bind-to-virtual-source.md

latest14.5 KB
Original Source

Bind to Virtual Sources

  • May 27, 2022
  • 7 minutes to read

This document demonstrates how to use the InfiniteAsyncSource or the PagedAsyncSource virtual source to bind GridControl to a data source.

Sample Data

The IssuesContext DbContext descendant is used as a sample data source in this tutorial.

Tip

The DevExpress virtual sources support Entity Framework, Entity Framework Core, and XPO sources. Refer to the following topic for details: Bind the WPF Data Grid to any Data Source with Virtual Sources.

Install the EntityFramework NuGet package.

Add the following code to your application.

Sample Data

csharp
using System.Collections.Generic;

public class Issue {
    public int Id { get; set; }
    public string Subject { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
    public DateTime Created { get; set; }
    public int Votes { get; set; }
    public Priority Priority { get; set; }
    public Issue() {
        Created = DateTime.Now;
    }
}
public enum Priority { Low, BelowNormal, Normal, AboveNormal, High }

public class User {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual ICollection<Issue> Issues { get; set; }
}
vb
Imports System.Collections.Generic

Public Class Issue
    Public Property Id As Integer
    Public Property Subject As String
    Public Property UserId As Integer
    Public Overridable Property User As User
    Public Property Created As Date
    Public Property Votes As Integer
    Public Property Priority As Priority

    Public Sub New()
        Created = Date.Now
    End Sub
End Class

Public Enum Priority
    Low
    BelowNormal
    Normal
    AboveNormal
    High
End Enum

Public Class User
    Public Property Id As Integer
    Public Property FirstName As String
    Public Property LastName As String
    Public Overridable Property Issues As ICollection(Of Issue)
End Class
csharp
using System;
using System.Data.Entity;
using System.Linq;

public class IssuesContextInitializer
    : DropCreateDatabaseIfModelChanges<IssuesContext> {

    public static void ResetData() {
        using(var context = new IssuesContext()) {
            context.Users.Load();
            context.Users.RemoveRange(context.Users);
            context.SaveChanges();
            CreateData(context);
        }
    }

    protected override void Seed(IssuesContext context) {
        base.Seed(context);
        CreateData(context);
    }

    static void CreateData(IssuesContext context) {
        var users = OutlookDataGenerator.Users
            .Select(x =>
            {
                var split = x.Split(' ');
                return new User() {
                      FirstName = split[0],
                      LastName = split[1]
                };
            })
            .ToArray();
        context.Users.AddRange(users);
        context.SaveChanges();

        var rnd = new Random(0);
        var issues = Enumerable.Range(0, 1000)
            .Select(i => new Issue()
            {
                Subject = OutlookDataGenerator.GetSubject(),
                UserId = users[rnd.Next(users.Length)].Id,
                Created = DateTime.Today.AddDays(-rnd.Next(30)),
                Priority = OutlookDataGenerator.GetPriority(),
                Votes = rnd.Next(100),
            })
            .ToArray();
        context.Issues.AddRange(issues);

        context.SaveChanges();
    }
}
vb
Imports System
Imports System.Data.Entity
Imports System.Linq

Public Class IssuesContextInitializer
    Inherits DropCreateDatabaseIfModelChanges(Of IssuesContext)

    ': DropCreateDatabaseAlways<IssuesContext> { 

    Public Shared Sub ResetData()
        Using context = New IssuesContext()
            context.Users.Load()
            context.Users.RemoveRange(context.Users)
            context.SaveChanges()
            CreateData(context)
        End Using
    End Sub

    Protected Overrides Sub Seed(ByVal context As IssuesContext)
        MyBase.Seed(context)
        CreateData(context)
    End Sub

    Private Shared Sub CreateData(ByVal context As IssuesContext)
        Dim users = OutlookDataGenerator.Users.[Select](Function(x)
                                                            Dim split = x.Split(" "c)
                                                            Return New User() With {
                                                                .FirstName = split(0),
                                                                .LastName = split(1)
                                                            }
                                                        End Function).ToArray()
        context.Users.AddRange(users)
        context.SaveChanges()
        Dim rnd = New Random(0)
        Dim issues = Enumerable.Range(0, 1000).[Select](Function(i) New Issue() With {
            .Subject = OutlookDataGenerator.GetSubject(),
            .UserId = users(rnd.Next(users.Length)).Id,
            .Created = Date.Today.AddDays(-rnd.Next(30)),
            .Priority = OutlookDataGenerator.GetPriority(),
            .Votes = rnd.Next(100)
        }).ToArray()
        context.Issues.AddRange(issues)
        context.SaveChanges()
    End Sub
End Class
csharp
using System.Data.Entity;

public class IssuesContext : DbContext {
    static IssuesContext() {
        Database.SetInitializer(new IssuesContextInitializer());
    }
    public IssuesContext() { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Issue>()
            .HasIndex(x => x.Created);

        modelBuilder.Entity<Issue>()
            .HasIndex(x => x.Votes);
    }

    public DbSet<Issue> Issues { get; set; }
    public DbSet<User> Users { get; set; }
}
vb
Imports System.Data.Entity

Public Class IssuesContext
    Inherits DbContext

    Shared Sub New()
        Database.SetInitializer(New IssuesContextInitializer())
    End Sub

    Public Sub New()
    End Sub

    Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
        MyBase.OnModelCreating(modelBuilder)
        modelBuilder.Entity(Of Issue)().HasIndex(Function(x) x.Created)
        modelBuilder.Entity(Of Issue)().HasIndex(Function(x) x.Votes)
    End Sub

    Public Property Issues As DbSet(Of Issue)
    Public Property Users As DbSet(Of User)
End Class
csharp
public static class OutlookDataGenerator {
    static Random rnd = new Random(0);
    static string[] Subjects = new string[] { "Developer Express MasterView. Integrating the control into an Accounting System.",
                                            "Web Edition: Data Entry Page. There is an issue with date validation.",
                                            "Payables Due Calculator is ready for testing.",
                                            "Web Edition: Search Page is ready for testing.",
                                            "Main Menu: Duplicate Items. Someone must review all menu items in the system.",
                                            "Receivables Calculator. Where can I find the complete specs?",
                                            "Ledger: Inconsistency. Please fix it.",
                                            "Receivables Printing module is ready for testing.",
                                            "Screen Redraw. Someone must look at it.",
                                            "Email System. What library are we going to use?",
                                            "Cannot add new vendor. This module doesn't work!",
                                            "History. Will we track sales history in our system?",
                                            "Main Menu: Add a File menu. File menu item is missing.",
                                            "Currency Mask. The current currency mask is completely unusable.",
                                            "Drag & Drop operations are not available in the scheduler module.",
                                            "Data Import. What database types will we support?",
                                            "Reports. The list of incomplete reports.",
                                            "Data Archiving. We still don't have these features in our application.",
                                            "Email Attachments. Is it possible to add multiple attachments? I haven't found a way to do this.",
                                            "Check Register. We are using different paths for different modules.",
                                            "Data Export. Our customers asked us for export to Microsoft Excel."};

    public static readonly string[] Users = new string[] {
        "Peter Dolan",
        "Ryan Fischer",
        "Richard Fisher",
        "Tom Hamlett",
        "Mark Hamilton",
        "Steve Lee",
        "Jimmy Lewis",
        "Jeffrey McClain",
        "Andrew Miller",
        "Dave Murrel",
        "Bert Parkins",
        "Mike Roller",
        "Ray Shipman",
        "Paul Bailey",
        "Brad Barnes",
        "Carl Lucas",
        "Jerry Campbell",
    };

    public static string GetSubject() {
        return Subjects[rnd.Next(Subjects.Length - 1)];
    }

    public static string GetFrom() {
        return Users[rnd.Next(Users.Length)];
    }
    public static Priority GetPriority() {
        return (Priority)rnd.Next(5);
    }
}
vb
Public Module OutlookDataGenerator
    Private rnd As Random = New Random(0)
    Private Subjects As String() = New String() {"Developer Express MasterView. Integrating the control into an Accounting System.", "Web Edition: Data Entry Page. There is an issue with date validation.", "Payables Due Calculator is ready for testing.", "Web Edition: Search Page is ready for testing.", "Main Menu: Duplicate Items. Someone must review all menu items in the system.", "Receivables Calculator. Where can I find the complete specs?", "Ledger: Inconsistency. Please fix it.", "Receivables Printing module is ready for testing.", "Screen Redraw. Someone must look at it.", "Email System. What library are we going to use?", "Cannot add new vendor. This module doesn't work!", "History. Will we track sales history in our system?", "Main Menu: Add a File menu. File menu item is missing.", "Currency Mask. The current currency mask is completely unusable.", "Drag & Drop operations are not available in the scheduler module.", "Data Import. What database types will we support?", "Reports. The list of incomplete reports.", "Data Archiving. We still don't have these features in our application.", "Email Attachments. Is it possible to add multiple attachments? I haven't found a way to do this.", "Check Register. We are using different paths for different modules.", "Data Export. Our customers asked us for export to Microsoft Excel."}
    Public ReadOnly Users As String() = New String() {"Peter Dolan", "Ryan Fischer", "Richard Fisher", "Tom Hamlett", "Mark Hamilton", "Steve Lee", "Jimmy Lewis", "Jeffrey McClain", "Andrew Miller", "Dave Murrel", "Bert Parkins", "Mike Roller", "Ray Shipman", "Paul Bailey", "Brad Barnes", "Carl Lucas", "Jerry Campbell"}

    Public Function GetSubject() As String
        Return Subjects(rnd.Next(Subjects.Length - 1))
    End Function

    Public Function GetFrom() As String
        Return Users(rnd.Next(Users.Length))
    End Function

    Public Function GetPriority() As Priority
        Return CType(rnd.Next(5), Priority)
    End Function
End Module

Bind the GridControl to Data

  1. Switch to the design view. Open the GridControl‘s Quick Actions and invoke the Items Source Wizard.

  2. Select the IssuesContext data source.

  3. Select the Issue table.

  4. Select the InfiniteAsyncSource binding model to display data with infinite scrolling. Alternatively, you can select the PagedAsyncSource model to display data in pages.

  5. Ensure that the Key Property is set to Id.

  6. Select Code-Behind to generate binding code in MainWindow.xaml.cs/MainWindow.xaml.vb. To generate binding code in a view model, refer to the MVVM Technique section instead.

Run the application.

MVVM Technique

To generate the binding code in a view model, follow these steps.

Create a ViewModel template that implements ViewModelBase and rebuild the solution:

csharp
using DevExpress.Mvvm;

namespace WPFBlankAppWithDatabase {
    public class ViewModel : ViewModelBase {

    }
}
vb
Imports DevExpress.Mvvm

Namespace WPFBlankAppWithDatabase
    Public Class ViewModel
        Inherits ViewModelBase

        End Sub
    End Class
End Namespace

Perform steps 1-5.

Select View Model to add the code to your view model.

Click Select a Data Context. Select the ViewModel class and click OK.

Enable the Set selected class as the data context option and click Finish.

The Items Source Wizard generates data binding code in the ViewModel and specifies data context and GridControl options in XAML. Run the application to see the result.