How to Build a Windows 11 Dashboard with .NET WinUI Charts
Tags: webdev, devops, dotnet, tutorial
Published: 2024-05-24 18:28:51

---
canonical_url: https://developer.mescius.com/blogs/how-to-build-a-windows-11-dashboard-with-net-winui-charts
description: Learn how to build a Windows 11 dashboard with .NET WinUI charts. See more from ComponentOne today.
---
**What You Will Need**
- ComponentOne WinUI & MAUI Edition
- Visual Studio 2022

**Controls Referenced**
- [FlexChart for WinUI](https://developer.mescius.com/componentone/docs/winui/online-winui/flexchart-overview.html)

**Tutorial Concept**

Learn how to build a data-bound dashboard for Windows 11 desktop using WinUI 3.0 and ComponentOne FlexChart.

---

In today's data-driven world, having a clear and accessible way to analyze data is essential for making informed decisions. To address this need, dashboards are preferable solutions as they are designed for both technical and non-technical audiences. Dashboards make complex data easy to understand by delivering valuable insights through charts and graphs.

In this blog, we will develop a Windows dashboard app for a hospital system that shows patient information. We are using the chart and datagrid controls from our [ComponentOne WinUI control](https://developer.mescius.com/componentone/winui-controls "https://developer.mescius.com/componentone/winui-controls") suite to showcase different aspects of patient data. The final dashboard will look like this:

![WinUI Dashboard](//cdn.mescius.io/umb/media/iiagodrh/final-dashboard.png?rmode=max&width=743&height=428)

Let’s break down the process of developing the dashboard into the following steps:

*   [Setup a WinUI Project and Add Required Dependencies](#Setup)
*   [Create the Dashboard Blueprint](#Create)
*   [Databind the Dashboard](#Databind)
*   [Sync the Modified Data with Charts](#Sync)
*   [View and Modify Data of a Particular Patient](#View)

## <a id="Setup"></a>Setup a WinUI Project and Add Required Dependencies

We’re building this dashboard using WinUI 3, which is used to create modern, Universal Windows applications, otherwise known as Microsoft Store apps. It uses XAML UI components, which are similar to WPF.

Let’s start by creating a WinUI project in Visual Studio 2022 and following the steps below:

1\. Open Visual Studio, and select **File->New->Project.**

2\. Search “WinUI template” in the search box and select “**Blank App, packaged (WinUI 3 in Desktop)**”.

![WinUI Template](//cdn.mescius.io/umb/media/vxkpe4gf/winui-template.png?rmode=max&width=721&height=411)

<span>3\.</span> Enter the Project Name and click the “Create” button.

4\. Now that we have successfully set up our project, it is time to add all the required dependencies. We are adding FlexGrid and FlexChart dependencies to show the grid and charts in our dashboard. Follow the below steps to install NuGet Packages:

<strongr>a. In the </strongr>**Solution Explorer, right-click on the project and select "Manage NuGet packages."**

![Solution Explorer](//cdn.mescius.io/umb/media/nandbqkl/solution-explorer.png?rmode=max&width=329&height=471)

b. Search “C1.WinUI.Grid” in the search bar and install the latest version of the C1.WinUI.Grid NuGet package.

![Nuget Package](//cdn.mescius.io/umb/media/msenygpu/nuget-package.png?rmode=max&width=678&height=203)

Similarly, you can install the “C1.WinUI.Chart” NuGet package to use C1 WinUI Charts in your project.

Now, we have set up a WinUI project and added the required Dependencies.

## <a id="Create"></a>Create the Dashboard Blueprint

In this step, we are creating a dashboard UI with a FlexGrid that showcases all the patients' records in an organized table, as well as three different types of FlexChart controls that show the following metrics:

*   **Line Chart:** Shows patient appointments over the years
*   **Pie Chart:** Shows the distribution of medical conditions of patients
*   **Column Chart:** Shows insurance providers registered by patients

Let’s follow the below steps to create a dashboard UI:

1\. Add XMLNS attributes in the Window tag of MainWindow.xaml file:

```
    xmlns:c1grid="using:C1.WinUI.Grid"
    xmlns:c1chart="using:C1.WinUI.Chart"
```

2\. Add C1FlexGrid and C1FlexChart controls in Xaml by replacing the <StackPanel> block with the following Xaml code:

```
    <Grid Background="Black">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="1.5*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition Height="4*"/>
            <RowDefinition Height="3*"/>
        </Grid.RowDefinitions>
        <TextBlock Text="Hospital Records" FontSize="25" Foreground="White" FontWeight="Bold" VerticalAlignment="Center" Margin="10,0,0,0"/>
        <TextBlock x:Name="patientTxt" FontSize="18" Foreground="White" FontWeight="Bold" VerticalAlignment="Center" Margin="10,0,0,0" Grid.Column="1"/>

        <!--Hospital Grid Data-->
        <c1grid:FlexGrid x:Name="patientRecordsGrid" Margin="0,0,5,5" Background="#4d4d4d" Foreground="White" 
                         Grid.Row="1" HeadersVisibility="All" SelectionMode="RowRange" VerticalScrollBarVisibility="Visible"
                         HorizontalScrollBarVisibility="Visible" BorderBrush="White" BorderThickness="2" ColumnHeaderFontWeight="Bold" ColumnHeaderFontSize="18"/>

        <!--Patient's Admission Chart View over the years-->
        <c1chart:FlexChart x:Name="AdmissionChart" ChartType="LineSymbols" Foreground="White" BorderBrush="White" BorderThickness="2" Grid.Row="2" Margin="0,5,5,0" PlotMargin="80,40,120,60"></c1chart:FlexChart>

        <!--Medical Conditions Pie Chart-->
        <c1chart:FlexPie x:Name="MedicalConditionPieChart" Foreground="White" Footer="Medical Conditions" BorderBrush="White" BorderThickness="2" Grid.Row="1" Grid.Column="1" Margin="5,0,0,5"></c1chart:FlexPie>

        <!--Chart view for Insurance Providers registered by Patient-->
        <c1chart:FlexChart x:Name="InsuranceProviderChart" ChartType="Column" Foreground="White" BorderBrush="White" BorderThickness="2" Grid.Row="2" Grid.Column="1" Margin="5,5,0,0"></c1chart:FlexChart>
```

## <a id="Databind"></a>Databind the Dashboard

In the previous step, we created a blueprint for the dashboard. To see the actual functional application, let’s bind the data by following the steps below:

**1\. Add Binding Properties**

Firstly, create a ViewModel where we can add binding properties. The ViewModel acts as the data source for the UI where we can control the view.

You will also need to create the following required classes with their respective properties: Appointment.cs, GenderData.cs, MedicalCondition.cs, and InsuranceProvider.cs.  
Refer to the sample attached at the end of the blog for these classes.

Follow the steps below to add and initialize the binding properties:

a. Add a class named **HospitalViewModel.cs** by right-clicking on **Project->Add->Class**.

![Add Class](//cdn.mescius.io/umb/media/r1abwaqr/add-class.png?rmode=max&width=679&height=390)

b. Add required **ObservableCollection** properties in HospitalViewModel.cs class so we can link these with the Charts and Grid. Here, we add the following properties to fetch the patients' specific records.

```
    //Collection of Patient records for FlexGrid
    public ObservableCollection<Appointment> HospitalData;

    //Collection of Patient's Admission Gender-wise for Line Chart
    public ObservableCollection<GenderData> GenderWiseAdmissionData;

    //Collection of Medical Conditions Distribution for Pie Chart
    public ObservableCollection<MedicalCondition> MedicalConditionData;

    //Collection of Insurance Provider Distribution for Column Chart
    public ObservableCollection<InsuranceProvider> InsuranceProviderData;  
```

c. Create a constructor for the **HospitalViewModel** class to initialize binding properties by deserializing the JSON. The JSON consists of “Patient’s records.”

```
    public HospitalViewModel()
    {
        //Load data from HospitalDataset.json to HospitalData collection
        var json = File.ReadAllText(Windows.ApplicationModel.Package.Current.InstalledPath + "/HospitalDataset.json");
        HospitalData = JsonConvert.DeserializeObject<ObservableCollection<Appointment>>(json);
        //Initialize collections for Charts
        GenderWiseAdmissionData = new ObservableCollection<GenderData>();
        MedicalConditionData = new ObservableCollection<MedicalCondition>();
        InsuranceProviderData = new ObservableCollection<InsuranceProvider>();
    }
```

**Note:** The HospitalDataSet.json file is included in the sample attached at the end of this blog.

**2\. Bind Properties in UI**

Now, all the required properties are created in the HospitalViewModel.cs class, and it's time to bind these properties to the UI to reflect the data under the ViewModel’s collection properties.

Follow the steps below to bind all required ViewModel properties to the UI in the MainWindow.Xaml file:

a. Initialize the **HospitalViewModel** instance under the MainWindow class in the **MainWindow.Xaml.cs** file so we can bind any accessible properties of HospitalViewModel to the MainWindow.Xaml.

```
    public HospitalViewModel vm { get; } = new(); 
```

b. Bind the **HospitalData** property to the ItemsSource of the FlexGrid in the MainWindow.xaml file so that the FlexGrid reflects all the records of the **HospitalData** collection. Update the FlexGrid code in MainWindow.xaml as below:

```
    <c1grid:FlexGrid x:Name="patientRecordsGrid" ItemsSource="{x:Bind vm.HospitalData}"
                     Margin="0,0,5,5" Background="#4d4d4d" Foreground="White" Grid.Row="1"
                     HeadersVisibility="All" SelectionMode="RowRange" VerticalScrollBarVisibility="Visible" 
                     HorizontalScrollBarVisibility="Visible" BorderBrush="White" BorderThickness="2" 
                     ColumnHeaderFontWeight="Bold" ColumnHeaderFontSize="18"/>
```

c. Bind the **GenderWiseAdmissionData** property to the ItemsSource of the AdmissionChart (Line Chart). Then, add 'Series' under the chart for genders and set BindingX="Year" to visualize the Gender-wise data over the years. You can also style the axis of FlexChart accordingly.

Update the AdmissionChart code in MainWindow.xaml file as below:

```
    <c1chart:FlexChart x:Name="AdmissionChart" ItemsSource="{x:Bind vm.GenderWiseAdmissionData}" BindingX="Year" ChartType="LineSymbols" Foreground="White" BorderBrush="White" BorderThickness="2" Grid.Row="2" Margin="0,5,5,0">
        <!--Add Series-->
        <c1chart:FlexChart.Series>
            <c1chart:Series Binding="Male" SeriesName="Male">
                <c1chart:Series.DataLabel>
                    <c1chart:DataLabel Content=" Male({Year}) : {Male:0}" Position="Bottom" Offset="20" />
                </c1chart:Series.DataLabel>
            </c1chart:Series>
            <c1chart:Series Binding="Female" SeriesName="Female">
                <c1chart:Series.DataLabel>
                    <c1chart:DataLabel Content=" Female({Year}) : {Female:0}" Position="Top" Offset="10"  />
                </c1chart:Series.DataLabel>
            </c1chart:Series>
        </c1chart:FlexChart.Series>
        <!--Style Axis-->
        <c1chart:FlexChart.AxisY>
            <c1chart:Axis  Title="No. of Appointments">
                <c1chart:Axis.TitleStyle>
                    <c1chart:ChartStyle Stroke="White" FontSize="15" FontWeight="Bold"/>
                </c1chart:Axis.TitleStyle>
            </c1chart:Axis>
        </c1chart:FlexChart.AxisY>
        <c1chart:FlexChart.AxisX>
            <c1chart:Axis Title="Years">
                <c1chart:Axis.TitleStyle>
                    <c1chart:ChartStyle Stroke="White" FontSize="15" FontWeight="Bold"/>
                </c1chart:Axis.TitleStyle>
            </c1chart:Axis>
        </c1chart:FlexChart.AxisX>
    </c1chart:FlexChart>
```

In the same way, you can add 'Series' and bind with respective properties for the other two charts. Refer to the Xaml file for other charts in the attached sample at the end of the blog.

Now, we have bound all HospitalViewModel’s properties in the UI, which looks like this:

![HospitalViewModel Properties](//cdn.mescius.io/umb/media/as3dzpsh/hospitalviewmodel-properties.png?rmode=max&width=693&height=399)

## <a id="Sync"></a>Sync the Modified Data with Charts

At this point, we can see records in the FlexGrid, and all required properties are bound to the UI. However, not all the charts visualize the data, and they are not synced with FlexGrid’s ItemsSource (Hospitaldata). Let’s sync the data with Charts.

1.  Create an **UpdateChartData**() method in HospitalViewModel.cs class and update every collection for chart data as per their use case.

```
    public void UpdateChartData()
    {
        //Clear all existing chart's records
        GenderWiseAdmissionData.Clear();
        MedicalConditionData.Clear();
        InsuranceProviderData.Clear();

        //Update GenderWiseAdmissionData Collection
        var yearWiseData = HospitalData.DistinctBy(x => x.Year).OrderBy(x => x.Year);
        foreach (var data in yearWiseData)
        {
            var male = HospitalData.Where(x => x.Year == data.Year).Count(x => x.Gender == "Male");
            var female = HospitalData.Where(x => x.Year == data.Year).Count(x => x.Gender == "Female");
            GenderWiseAdmissionData.Add(new GenderData() { Year = data.Year, Male = male, Female = female });
        }

        //Update MedicalConditionData Collection
        var medicalCondition = HospitalData.DistinctBy(x => x.MedicalCondition).OrderBy(x => x.MedicalCondition);
        foreach (var data in medicalCondition)
        {
            var admissionCount = HospitalData.Where(x => x.MedicalCondition == data.MedicalCondition).Count();
            MedicalConditionData.Add(new MedicalCondition() { Name = data.MedicalCondition, AdmissionCount = admissionCount });
        }

        //Update InsuranceProviderData Collection
        var insuranceProviders = HospitalData.DistinctBy(x => x.InsuranceProvider).OrderBy(x => x.InsuranceProvider);
        foreach (var data in insuranceProviders)
        {
            var admissionCount = HospitalData.Where(x => x.InsuranceProvider == data.InsuranceProvider).Count();
            InsuranceProviderData.Add(new InsuranceProvider() { Name = data.InsuranceProvider, Customers = admissionCount });
        }
    }
```

2\. Call the **UpdateChartData**() method in HospitalViewModel’s constructor to initialize the chart with the data once the instance of HospitalViewModel is created.

```
    public HospitalViewModel()
    {
        ……
        //Update Data on first Load
        UpdateChartData();
        ……
    }
```

3\. Handle the **CollectionChanged** event of the **HospitalData** collection and update the chart’s data once the **CollectionChanged** event fires. This will update the chart’s data when we modify FlexGrid records.

```
    HospitalData.CollectionChanged += (s, e) => 
    {
        //Update data once Hospital Data updates
        UpdateChartData();
    };

```
Now, the chart’s data will be shown with the grid data as below:

![Charts Grid Data](//cdn.mescius.io/umb/media/mm4fb2cr/charts-grid-data.png?rmode=max&width=704&height=402)

## <a id="View"></a>View and Modify Data of a Particular Patient

Now, the dashboard is almost complete. We can visualize data on FlexGrid and FlexCharts. It’s time to make it more interactive.

Currently, all chart visualization is happening based on the data of all patients. What if we can visualize a particular patient’s information on different parameters? This will help us to analyze a particular patient's data more accurately.

For this, we need to add a little more code by following the steps below:

1\. Create a **VisualizePatientRecords(string patientId)** method in HospitalViewModel.cs class and update every chart’s collection as per their PatientId.

```
    public void VisualizePatientRecords(string patientId)
    {
        //Clear all existing chart's records
        GenderWiseAdmissionData.Clear();
        MedicalConditionData.Clear();
        InsuranceProviderData.Clear();

        //Patient's GenderWiseAdmissionData Collection
        var yearWiseData = HospitalData.DistinctBy(x => x.Year).OrderBy(x => x.Year);
        foreach (var data in yearWiseData)
        {
            int? male = HospitalData.First(x => x.PatientId == patientId).Gender == "Male" ? HospitalData.Where(x => x.Year == data.Year && x.PatientId == patientId).Count(x => x.Gender == "Male") : null;
            int? female = HospitalData.First(x => x.PatientId == patientId).Gender == "Female" ? HospitalData.Where(x => x.Year == data.Year && x.PatientId == patientId).Count(x => x.Gender == "Female") : null;
            GenderWiseAdmissionData.Add(new GenderData() { Year = data.Year, Male = male, Female = female });
        }

        //Patient's MedicalConditionData Collection
        var medicalCondition = HospitalData.DistinctBy(x => x.MedicalCondition).OrderBy(x => x.MedicalCondition);
        foreach (var data in medicalCondition)
        {
            var admissionCount = HospitalData.Where(x => x.MedicalCondition == data.MedicalCondition && x.PatientId == patientId).Count();
            if (admissionCount > 0)
                MedicalConditionData.Add(new MedicalCondition() { Name = data.MedicalCondition, AdmissionCount = admissionCount });
        }

        //Patient's InsuranceProviderData Collection
        var insuranceProviders = HospitalData.DistinctBy(x => x.InsuranceProvider).OrderBy(x => x.InsuranceProvider);
        foreach (var data in insuranceProviders)
        {
            var claimsCount = HospitalData.Where(x => x.InsuranceProvider == data.InsuranceProvider && x.PatientId == patientId).Count();
            if (claimsCount > 0)
                InsuranceProviderData.Add(new InsuranceProvider() { Name = data.InsuranceProvider, Customers = claimsCount });
        }
    }
```

2\. Handle the **SelectionChanged** event of FlexGrid to call the **VisualizePatientRecords()** method.  It will display data of the specific patient in the charts when any row is selected in the grid.

```
    patientRecordsGrid.SelectionChanged += (s, e) =>
    {
        if (patientRecordsGrid.Selection != null)
        {
            //Show a particular patient record
            if (patientRecordsGrid.Selection.RowsCount == 1)
            {
                var patient = patientRecordsGrid.SelectedItems[0] as Appointment;
                vm.VisualizePatientRecords(patient.PatientId);
                patientTxt.Text = patient.Name + "(" + patient.PatientId + ")";
            }
            //Show all records
            else
            {
                if (isSelectAll == false)
                {
                    patientRecordsGrid.Select(e.CellRange.Row, patientRecordsGrid.ViewRange.Column);
                }
                isSelectAll = true;
                vm.UpdateChartData();
                patientTxt.Text = string.Empty;
            }
        }
        //Show all records
        else
        {
            vm.UpdateChartData();
            patientTxt.Text = string.Empty;
        }
    };
```

3\. Handle the **CellEditEnded** event of FlexGrid and call the **VisualizePatientRecords()** method to update the specific patient's data. This updates the chart immediately when we edit any record in the grid.

```
    patientRecordsGrid.CellEditEnded += (s, e) =>{
        var patient = patientRecordsGrid.SelectedItems[0] as Appointment;
        vm.VisualizePatientRecords(patient.PatientId);
        patientTxt.Text = patient.Name + "(" + patient.PatientId + ")";
    };
```

This is how our dashboard works to showcase particular patients' records:

![WinUI Dashboard animation](//cdn.mescius.io/umb/media/nqzglto3/winui_dashboard_animation.gif?rmode=max&width=715&height=390)

## Conclusion

We hope this blog helps you create an interactive WinUI dashboard using C1 controls. [Download the full sample](https://cdn.mescius.io/umb/media/knnmhhtm/dashboardapp.zip) to customize it further, fit your requirements, and showcase different metrics in your WinUI dashboard.

To learn more about these advanced WinUI controls, check out the documentation and sample demos in the links below:

*   [WinUI Documentation](https://developer.mescius.com/componentone/docs/winui/online-winui/overview.html "https://developer.mescius.com/componentone/docs/winui/online-winui/overview.html")
*   [WinUI Samples](https://github.com/GrapeCity/ComponentOne-WinUI-Samples "https://github.com/GrapeCity/ComponentOne-WinUI-Samples")