C# Thinking outside the norm

Introduction
Had a forum question today where a developer wanted to load a TreeView in Windows Forms were data was read from a database and in turn caused the user interface to become unresponsive.

They asked about BackGroundWorker component or asynchronous way (async/await task) but had never worked with any of these.

My solution
Since the idea is to use a delegate/event this path will work on any control ranging from TreeView to ListView or DataGridView the example given uses a ListView.

Start off with a class which represents returning data.

using System;
namespace IteratingCodeSample.Classes
{
    public class Countries
    {
        public int CountryIdentifier { getset; }
        public string Name { getset; }
        /// <summary>
        /// Provides easy way to add a country to a ListView
        /// </summary>
        public string[] ItemArray => new[]
        {
            Name,
            Convert.ToString(CountryIdentifier)
        };
 
        public override string ToString() => Name;
 
    }
 
}

Next create a method to read data from a database and while reading use a delegate to pass a country to listeners (will get to that shortly).

using System.Data.SqlClient;

using System.Threading.Tasks;
 
namespace IteratingCodeSample.Classes
{
    public class Operations
    {
        public delegate void DisplayInformation(Countries sender);
        public static event DisplayInformation DisplayInformationHandler;
 
        private static string _connectionString = "Data Source=.\\sqlexpress;Initial " +
                                          "Catalog=northwind2020;Integrated Security=True";
        /// <summary>
        /// Get countries, the user interface remains responsive
        /// </summary>
        /// <returns></returns>
        public static async Task GetCountries()
        {
 
            using (var cn = new SqlConnection {ConnectionString = _connectionString})
            {
                using (var cmd = new SqlCommand {Connection = cn})
                {
                    await cn.OpenAsync();
                    cmd.CommandText = "SELECT CountryIdentifier, Name FROM dbo.Countries;";
                    var reader = await cmd.ExecuteReaderAsync();
 
                    while (reader.Read())
                    {
                        /*
                         * Since there are only a few records let's act like more is going on
                         */
                        await Task.Delay(500);
 
                        var country = new Countries()
                        {
                            CountryIdentifier = reader.GetInt32(0),
                            Name = reader.GetString(1)
                        };
                        
                        DisplayInformationHandler?.Invoke(country);
                    }
                }
            }
        }
 
    }
}

The form code is simple, subscribe to DisplayInformationHandler and add a country to the ListView.

using System;
using System.Windows.Forms;
using IteratingCodeSample.Classes;
 
namespace GetCountriesIterator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            Operations.DisplayInformationHandler += Operations_DisplayInformationHandler;
 
            Shown += Form1_Shown;
        }
 
        private async void Form1_Shown(object sender, EventArgs e)
        {
            await Operations.GetCountries();
 
            CountryListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
            CountryListView.FocusedItem = CountryListView.Items[0];
            CountryListView.Items[0].Selected = true;
 
            ActiveControl = CountryListView;
        }
 
        private void Operations_DisplayInformationHandler(Countries sender)
        {
            CountryListView.Items.Add(new ListViewItem(sender.ItemArray) );
        }
    }
}

Source code

The source resides in the following GitHub repository, frontend project, backend project.

Summary

Many developers do not take time to look past what they are comfortable with, in many cases it's not learning to work with asynchronous coding and/or delegates. This is a very simply way for a windows form developer to learn from. Next steps are to have them consider WPF and .NET Core solutions.

Comments

Popular posts from this blog

VB.NET Working with Delegate and Events

Coders asking questions in online forums

GitHub download partial repository