TL;DR: Want to build a responsive Employee Onboard Tracker using .NET MAUI DataGrid UI? This guide walks you through using DataGridTemplateColumn to render progress bars, bind checklist data with ObservableCollection, and display nested onboarding tasks, all using MVVM and real-time UI updates. Perfect for developers building onboarding dashboards or task trackers with .NET MAUI DataGrid.
Building a responsive and interactive Employee Onboarding Tracker UI is a common challenge for developers working on HR or workflow applications.
In this blog post, we’ll explore how to use .NET MAUI DataGrid to create a dynamic onboarding dashboard. You’ll learn how to bind data using MVVM, visualize progress with a custom progress bar, and display nested checklist items, all within a structured DataGrid.
Step 1: Defining employee class
We begin by creating the Employee model class, which includes properties like name, email, joining date, progress percentage, pending tasks, and a checklist. To support real-time UI updates, the class implements INotifyPropertyChanged. This ensures that any property change is immediately reflected in the UI.
public class Employee: INotifyPropertyChanged
{
private bool isSelected;
private string name;
private string email;
private DateTime dateOfJoining;
private int pendingTasks;
private int onboardingProgressPercentage;
private List checkedlists;
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged(nameof(Name));
}
}
public string Email
{
get { return email; }
set
{
email = value;
OnPropertyChanged(nameof(Email));
}
}
public DateTime DateOfJoining
{
get { return dateOfJoining; }
set
{
dateOfJoining = value;
OnPropertyChanged(nameof(DateOfJoining));
}
}
public int OnboardingProgressPercentage
{
get { return onboardingProgressPercentage; }
set
{
onboardingProgressPercentage = value;
OnPropertyChanged(nameof(OnboardingProgressPercentage));
}
}
public int PendingTasks
{
get { return pendingTasks; }
set
{
pendingTasks = value;
OnPropertyChanged(nameof(PendingTasks));
}
}
public List Checklists
{
get { return checkedlists; }
set
{
checkedlists = value;
OnPropertyChanged(nameof(Checklists));
}
}
public Employee()
{
}
}
Step 2: Generate sample data in the ViewModel
We shall populate the onboarding tracker with sample employee data. This is handled within the EmployeeOnboardingViewModel, which manages both the data and its interaction with the UI.
The Employees property is an ObservableCollection<Employee>, bound to the DataGrid’s ItemsSource. This enables dynamic rendering and ensures that updates to the collection are reflected in real time.
public partial class EmployeeOnboardingViewModel : INotifyPropertyChanged
{
private ObservableCollection<Employee> employees;
public ObservableCollection<Employee> Employees
{
get
{
return employees;
}
set
{
employees = value;
OnPropertyChanged(nameof(Employees));
}
}
}
private void GenerateEmployees()
{
// Creating checklist items with random completion status for demo purposes
var tyrionChecklist = CreateChecklistItems(3); // 3 items completed
var sansaChecklist = CreateChecklistItems(4); // 4 items completed
// More checklists...
Employees.Add(new Employee
{
Name = "Tyrion Lannister",
Email = "tyrion@xyz.com",
DateOfJoining = new DateTime(2021, 11, 18),
OnboardingProgressPercentage = 33,
PendingTasks = 6,
Checklists = tyrionChecklist
});
// More employees...
}
Step 3: Defining columns
To maintain a clean and purposeful UI, we define a Columns collection that explicitly controls which fields are displayed in the DataGrid. This approach avoids auto-generating columns, allowing us to selectively present only the most relevant onboarding data.
Each column is carefully tailored to represent specific properties such as selection status, onboarding progress, and checklist items. By doing so, we ensure clarity, consistency, and a user interface that aligns tightly with the onboarding workflow.
public partial class EmployeeOnboardingViewModel : INotifyPropertyChanged
{
// Columns and Data manipulation property definition
private ColumnCollection columns = new ColumnCollection();
public ColumnCollection Columns
{
get
{
return columns;
}
set
{
columns = value;
OnPropertyChanged(nameof(Columns));
}
}
private void InitializeColumns()
{
// Columns added here
}
Instead of auto-generating columns, we explicitly define each one in the ViewModel using:
- DataGridTextColumn for text fields
- DataGridNumericColumn for numbers
- DataGridCheckBoxColumn for selection
- DataGridTemplateColumn for custom UI, like progress bars and nested views
Each column uses a MappingName to bind to a specific property and a HeaderText for display. The columns below are added to a collection in the ViewModel and bound to the DataGrid control.
1. Selection column (Checkbox)
This column allows users to select rows individually or via a master checkbox in the header.
// CheckBox Column
var checkBoxColumn = new DataGridCheckBoxColumn()
{
MappingName = "IsSelected",
HeaderText = "",
Width = 50,
HeaderTemplate = new DataTemplate(() =>
{
var headerCheckBox = new Syncfusion.Maui.Buttons.SfCheckBox()
{
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center
};
headerCheckBox.SetBinding(Syncfusion.Maui.Buttons.SfCheckBox.IsCheckedProperty, new Binding() { Path = "IsChecked", Mode = BindingMode.TwoWay, Source = this });
return headerCheckBox;
})
};
2. Progress bar column (Template)
Displays a visual progress bar alongside a percentage label, bound to the OnboardingProgressPercentage property.
var progressColumn = new DataGridTemplateColumn()
{
MappingName = "OnboardingProgressPercentage",
HeaderText = "Onboarding Progress",
Width = 180,
CellTemplate = new DataTemplate(() =>
{
// Grid with progress bar and label
})
};
3. Checklists column with nested data
Displays a nested CollectionView within each cell inside the DataGridTemplateColumn to show all checklist items for the employee. Completed tasks are visually marked with a green check icon.
var checklistsColumn = new DataGridTemplateColumn()
{
MappingName = "Checklists",
HeaderText = "Checklists",
Width = 300,
CellTemplate = new DataTemplate(() =>
{
var collectionView = new CollectionView();
collectionView.SetBinding(CollectionView.ItemsSourceProperty, "Checklists");
collectionView.ItemTemplate = new DataTemplate(() =>
{
var grid = new Grid
{
ColumnDefinitions =
{
new ColumnDefinition { Width = GridLength.Star },
new ColumnDefinition { Width = GridLength.Auto }
},
Margin = new Thickness(2)
};
var taskLabel = new Label
{
Margin = new Thickness(5, 2),
HorizontalOptions = LayoutOptions.Start,
};
taskLabel.SetBinding(Label.TextProperty, "Task");
//s taskLabel.SetBinding(Label.BackgroundColorProperty, new Binding("IsCompleted", converter: new BoolToColorConverter()));
var checkLabel = new Label
{
Text = "✓",
TextColor = Colors.Green,
FontAttributes = FontAttributes.Bold,
Margin = new Thickness(5, 0, 5, 0)
};
checkLabel.SetBinding(Label.IsVisibleProperty, "IsCompleted");
grid.Add(taskLabel, 1, 0);
grid.Add(checkLabel, 0, 0);
return grid;
});
return collectionView;
})
};
Step 4: Designing the UI
Bind the UI to the EmployeeOnboardingViewModel using BindingContext. Then, the columns from the view model are bound to the SfDataGrid through the Columns property, enabling dynamic rendering.
<ContentPage.BindingContext>
<local:EmployeeOnboardingViewModel />
</ContentPage.BindingContext>
<syncfusion:SfDataGrid x:Name="dataGrid"
ItemsSource="{Binding Employees}"
Columns="{Binding Columns}"
SelectionMode="Multiple"
AutoGenerateColumnsMode="None"
</syncfusion:SfDataGrid>
Step 5: Handle data manipulation
With the UI now bound to the view model, the next step is to enable interactive features such as column visibility toggling, sorting, grouping, and filtering. These are handled through commands defined in the view model. Let’s define the following commands in the ViewModel:
- Column visibility: HideColumns, ShowAllColumns, HideAllColumns
- Sorting: SortColumns, ClearSort
- Grouping: GroupColumns, ClearGroup
- Filtering: FilterColumns, ClearFilter
public partial class EmployeeOnboardingViewModel: INotifyPropertyChanged
{
public ICommand HideColumns { get; set; } = null!;
public ICommand HideAllColumns { get; set; } = null!;
public ICommand ShowAllColumns { get; set; } = null!;
// define other commands
private void InitializeCommands()
{
HideColumns = new Command(ExecuteHideColumns);
ShowAllColumns = new Command(ExecuteShowAllColumns);
HideAllColumns = new Command(ExecuteHideAllColumns);
//initialize other commands
}
}
Each command is initialized and bound to UI actions, allowing users to interactively manipulate the DataGrid.
Step 6: Column visibility with commands
Column visibility is managed through commands like HideColumns, ShowAllColumns, and HideAllColumns, which are bound to UI actions. These commands trigger methods such as ExecuteHideAllColumns and ExecuteShowAllColumns, which loops through the column collection and updates the Visible property accordingly.
private void ExecuteHideColumns()
{
IsOpenForHideColumns = true;
}
private void ExecuteHideAllColumns()
{
foreach (var item in columns)
{
if (item.MappingName == "IsSelected")
continue;
item.Visible = false;
}
}
private void ExecuteShowAllColumns()
{
foreach (var item in columns)
{
if (item.MappingName == "IsSelected")
continue;
item.Visible = true;
}
}
In addition to managing column visibility, the onboarding tracker supports advanced interactions within the DataGrid, such as sorting, grouping, and filtering. These features are implemented using command-based logic, ensuring a consistent and maintainable architecture.
Sorting with commands
The SortColumns command manages sorting logic in the DataGrid. When triggered, it calls ExecuteAddSorting, which clears existing sort descriptions and adds new ones based on user input.
private void ExecuteAddSorting()
{
if (SelectedSortColumn != null)
{
SortColumnDescriptions.Clear();
var sortColumnDescription = new SortColumnDescription()
{
ColumnName = this.SelectedSortColumn.Name ?? string.Empty,
SortDirection = IsOnState ? ListSortDirection.Ascending : ListSortDirection.Descending
};
SortColumnDescriptions.Add(sortColumnDescription);
}
}
Group data with commands
The GroupColumns command organizes DataGrid content into logical categories. When executed, the ExecuteAddGrouping method clears existing group settings and applies new ones, helping users analyze onboarding data more effectively.
private void ExecuteAddGrouping()
{
if (SelectedGroupColumn != null)
{
GroupColumnDescriptions.Clear();
var groupColumnDescription = new GroupColumnDescription() { ColumnName = this.SelectedGroupColumn.Name ?? string.Empty };
GroupColumnDescriptions.Add(groupColumnDescription);
}
}
Filtering logic with commands
The FilterRecords method applies string or numeric filters based on selected column and condition. It uses helper methods like MakeStringFilter and MakeNumericFilter to evaluate each record.
public bool FilerRecords(object o)
{
if (SelectedColumn == null && string.IsNullOrEmpty(this.SelectedCondition))
return true;
double res;
bool checkNumeric = double.TryParse(this.FilterText, out res);
var item = o as Employee;
if (item != null && !string.IsNullOrEmpty(this.FilterText) && this.FilterText.Equals(string.Empty))
{
return true;
}
else
{
if (item != null && SelectedColumn != null)
{
if (checkNumeric && !(this.SelectedColumn.Name ?? string.Empty).Equals("All Columns") && !(this.SelectedCondition ?? string.Empty).Equals("Contains"))
{
bool result = this.MakeNumericFilter(item, this.SelectedColumn.Name, this.SelectedCondition);
return result;
}
else if ((this.SelectedColumn.Name ?? string.Empty).Equals("All Columns"))
{
if ((item.Name ?? string.Empty).ToString().ToLower().Contains(this.FilterText!.ToLower()) ||
(item.Email ?? string.Empty).ToString().ToLower().Contains(this.FilterText.ToLower()) ||
item.DateOfJoining.ToString().ToLower().Contains(this.FilterText.ToLower()) ||
item.OnboardingProgressPercentage.ToString().ToLower().Contains(this.FilterText.ToLower()) ||
item.PendingTasks.ToString().ToLower().Contains(this.FilterText.ToLower()) ||
(item.Checklists != null && item.Checklists.ToString().ToLower().Contains(this.FilterText.ToLower())))
{
return true;
}
return false;
}
else
{
bool result = this.MakeStringFilter(item, this.SelectedColumn.Name, this.SelectedCondition!);
return result;
}
}
}
return false;
}
After implementing all the above features, data binding, column customization, and command-based interactions, the final UI brings everything together in a responsive and user-friendly layout.
![]()
GitHub reference
Explore the complete implementation on GitHub to dive deeper into the onboarding tracker UI built with .NET MAUI DataGrid.
Conclusion
We explored how to build an Employee Onboarding Tracker UI using .NET MAUI DataGrid. You can create a structured and interactive onboarding dashboard by leveraging MVVM, custom column types, and nested checklist rendering. The approach supports real-time updates, progress tracking, and flexible data manipulation, which is ideal for task-driven applications.
If you’re a Syncfusion user, you can download the setup from the license and downloads page. Otherwise, you can download a free 30-day trial.
You can also contact us through our support forum, support portal, or feedback portal for queries. We are always happy to assist you!
Related Blogs
- Design Smarter Data Tables in .NET MAUI with the DataGrid Control
- Build a School Gradesheet App Easily with .NET MAUI DataGrid
- How to Build a Student Attendance App with .NET MAUI ListView and DataGrid
- Build a Real-Time Trading App Using .NET MAUI DataGrid
This article was originally published at Syncfusion.com.
Top comments (0)