Let's make your data visible using Wisej.NET and the DataGridView

One of those common tasks you end up doing with virtually any web application is to show data.

'Data' is a broad brush term. It might be as simple as showing some hardcoded text on the page, or as complicated as retrieving thousands of interconnected rows of data from a database.

A web application's success is often built on how well it presents data to users, so let's explore how we can connect UI to data using Wisej.NET.

Bind Individual UI Elements To Data (Simple Binding)

The first, and perhaps simplest way to get data to show up in your UI is to bind individual controls to data.

If you've worked with Windows, or WebForms in the past, you'll be familiar with the concept of adding instances of controls to your page.

In Wisej.NET we can add controls, then use them to show data.

For example, we could add a label control to a page, then set its Text property to the value we want to show:

But what if we want to show data via that label, for example from a database, or some other model that we happen to have access to from this page?

For that we need to drop down to the code for this page.

There, we can interact with the control directly. For example, here's how we might take the values from an instance of a class, and show them in our UI (via two label controls).

namespace WisejTutorials.Panels
{  
    public partial class SimpleDataBinding : Wisej.Web.UserControl
    {
        private UserDetails userDetails = new UserDetails { Name = "Nasa", Age = "42" };

        public SimpleDataBinding()
        {
            InitializeComponent();

            lblName.Text = userDetails.Name;
            lblAge.Text = userDetails.Age;            
        }
    }

    public class UserDetails
    {
        public string Name { get; set; }
        public string Age { get; set; }
    }
}

UserDetails is our model in this example.

When this page loads its constructor will be invoked. In there we can set the Text property for our two labels to the relevant values from the instance of the UserDetails class.

Once we've bound a control to a property like this the UI will be updated automatically if the value changes.

Bind Container Controls (Complex Binding)

So far so good, but what if we want to present a lot of data, for example rows from a database or API?

Wisej.NET includes a number of 'container controls' which can be used to show your data:

  • DataGridView

  • ListView

  • TreeView

  • ComboBox

  • ListBox

  • CheckedListBox

These are all useful in different circumstances and the DataGridView is a particularly handy "go-to" control for displaying structured, tabular data.

To use DataGridView we can start by pointing it to a data source.

Binding to a List

Let's say we want to display a table of movies.

Here's a small service to return a list of (hardcoded for the demo) movie details.

MovieService.cs

public class MovieService
{
    public Task<List<MovieDetails>> GetMovies()
    {
        return Task.FromResult(Movies.DemoData());
    }
}

The MovieDetails class looks like this.

public class MovieDetails
{
    public string Title { get; set; }
    public string Summary { get; set; }
    public int Year { get; set; }
}

For the purposes of the demo Movies.DemoData() returns a hardcoded list:

public static class Movies
{
    public static List<MovieDetails> DemoData()
    {
        return new List<MovieDetails>
        {
            new MovieDetails
            {
                Title = "The Godfather",
                Summary =
                    "The aging patriarch of an organized crime dynasty transfers control of his clandestine empire to his reluctant son.",
                Year = 1972
            },
            
            ...
        }
    }
}

Turning our attention to our Wisej.NET page, we can add an instance of the DataGridView control via the WYSIWYG editor.

Once we have that we can bind it to our movie data:

public partial class DataGridViewBinding : Wisej.Web.UserControl
{
    ...

    private void DataGridViewBinding_Load(object sender, EventArgs e)
    {
        LoadData();
    }

    private async void LoadData()
    {
       this.dgMovies.DataSource = await new MovieService().GetMovies();
    }       
}

Now, when we view this in the browser, we get a handy table showing all of our movies:

Each row is bound to a record in the data source (in this case, and instance of MovieDetails) and each cell is bound to a field in that record (Title, Summary, Year).

Binding to a Database

Naturally, in most web applications we ultimately want to display data from a database rather than a hardcoded list.

For this we can use ADO.NET or any other ORM/Data Access framework that works with .NET.

Once we go down this road it can be useful to introduce a BindingSource.

This acts as a sort of 'middle man' between data controls (like our DataGridView) and the underlying database.

For example, here's the same Movie Example, but using the popular Micro ORM - Dapper.

public partial class DapperExample : Wisej.Web.UserControl
{
    public DapperExample()
    {
        InitializeComponent();
        LoadData();
    }

    private async void LoadData()
    {
        using (var connection = new SQLiteConnection(DBConfig.ConnectionString))
        {
            this.moviesBindingSource.DataSource = await connection
            .QueryAsync<MovieDetails>("SELECT * FROM Movie");

            this.dgMovies.DataSource = moviesBindingSource;              
        }
    }
}

I've added a BindingSource to the page (via the WYSIWYG designer) and called it moviesBindingSource.

I've then used Dapper to query the database, specificaly to retrieve a list of movies.

This list is then assigned as the DataSource for the BindingSource.

Functionally this works exactly the same as our earlier example, except the data is now coming from a table in a SQLite database.

Customising the DataGridView

Once we've got data on the page we can customise the DataGridView in various ways, including changing the size of columns, formatting cells, and using different column types.

Choose your columns

By default, the DataGridView automatically shows all the available properties from the underlying data.

There are two ways to control which data is visible in your grid:

  • By tweaking the underlying model

  • By modifying the properties of the DataGridView iteself

Perhaps the simplest option is to to use the model itself to control what gets shown in the grid.

For example, here I've updated the Dapper query to select specific columns from the database (instead of using * to select all).

private async void LoadData()
{
    using (var connection = new SQLiteConnection(DBConfig.ConnectionString))
    {
        this.moviesBindingSource.DataSource = await connection
            .QueryAsync<MovieSummary>("SELECT Title, Summary FROM Movie");

        this.dgMovies.DataSource = moviesBindingSource;              
    }
} 

Note how this also uses a different model to before, a MovieSummary class.

public class MovieSummary
{
    public string Title { get; set; }
    public string Summary { get; set; }
}

Using the model to control which columns appear has the advantage that, if the model changes (for example, we add a property) the grid automatically reflects those changes (including the new property as a column).

Alternatively, we can take control over the columns by modifying the DataGridView itself.

If we set the AutoGenerateColumns property to false, we can manually choose which columns we want to display:

in this case I've specified a single column with the name Title and a DataPropertyName of Title.

WiseJ will look for a property called Title on the model and show its value if it exists.

Finally, whether using autogenerated columns, or specifying them ourselves, we can also customise the appearance of each column via number of handy properties. Here are some of the key ones:

All of the following properties can be set in code, or via the designer when editing columns for the DataGridView.

Set the size of each column

We can tweak the width of the column via the Width property.

this.dgMovies.Columns["Title"].Width = 200;

Change the format of values in a column

Chances are you're going to want to tweak the format of your data at some point. Whether it's showing dates in a specific format, or making sure your currency values include commas and currency symbols in all the right places.

For that we can use the DefaultCellStyle.Format property for a column.

For example, if our movie data included a full release date (DateTime) , we could get the release year from it using the Format property:

dgMovies.Columns["ReleaseDate"].DefaultCellStyle.Format = "yyyy";

Change the column header

You might want to show a different header for a column. We can do that via the HeaderText property.

dgMovies.Columns["Title"].HeaderText = "Movie Title";

Change a cell's appearance

You can tweak the style for all cells in a column using DefaultCellStyle.

For example, here's how to change the background colour:

dgMovies.Columns["Title"].DefaultCellStyle.BackColor = Color.AliceBlue;

With this, all cells for the Title column will have a subtle blue background.

In Summary

You can make your data visible in your Wisej.NET app using simple binding (for showing individual 'pieces of data') or complex binding, using one of Wisej.NET's numerous 'container' controls.

The DataGridView is a handy 'go to' option for displaying rows of data.

You can quickly get data into the grid using its DataSource property.

From there, you can tweak which data is visible by adding/removing properties from the underlying model, or by specifying which columns should be present in the DataGridView itself.

Finally, you can control the appearance of columns in the grid by explicitly setting column properties, in code, or via the WYSIWYG designer.

Last updated

Logo

© Ice Tea Group LLC, All Rights Reserved.