JavaScript Error

You currently have JavaScript disabled on your web browser.

This website uses JavaScript, and This web page needs JavaScript activated to work correctly.

Please active JavaScript on your web browser and then refresh this web page.



ListView



example1

The ListView control is found in the System.Windows.Forms namespace within the System.Windows.Forms.dll. In this blog post I am referring to the ListView control that is available in C# .NET-Core (.NET 6.0) with Visual Studio 2022 (although this code example might still work OK with older .NET versions).

The ListView control can be used to display a collection of items to the user, which the user can then view and select items from. The ListView control has five different view modes which can be set using the ListView control object's View property: LargeIcon, Details, SmallIcon, List, and Tile (default is LargeIcon).

The ListViewItem class represents an Item within a ListView control. Each Item is displayed in the ListView control with Item text, along with optional image icons. Items can be displayed as large icons, as small icons, or as small icons in a vertical list.

Each Item can also have multiple SubItems, which contain additional information that is related to the parent Item. The Details view allows you to display the Item and its SubItems in a grid with column headers that identify the information of a SubItem. The Tile view can also display information about an Items SubItems, can can display the Item and its SubItems as a tile that contains a large icon next to the SubItems textual information.

Each Item and SubItem can be selected as one whole, so that if you select an Item's SubItem then that Item will be selected. They can also be selected individually, allowing you to program some task to be performed when selected. Alternatively, setting the FullRowSelect property to True will the entire Item and its SubItems to be selected whenever one of an Items SubItems are selected.

Tip: When View mode is set to Design, set each Columns Width value to -2 to have that column immediately auto-size itself. The columns width value will immediately change to the new columns size value, therefore to auto-size the column again after adding new values to column cells then you will need to reapply the -2 value to the columns width property value again to again have it auto-size itself.


Example Source Code

This example uses a ListView control, along with a GroupBox control, three Label controls, a ComboBox control, two TextBox controls, and three Button controls.

To add the ListView control to your form, you can double click on its name (i.e. ListView) as listed in the Toolbox window panel within the Form editor window. Alternatively, you can single click on it and then drag and drop it onto your form, to position it more closer to where you want it to be positioned at. Once it is added to the form then it will appear on the forms surface area having default control values.

After you have added the ListView control to your form, then once you select it then you can view and edit that objects property values in the Properties window within the Forms editor window, where you can then change the controls Name, Items, and other properties as you desire.

In the following example, I added a ListView control to my form, and then resized it so that it fits the Form area as shown below. While it was still selected, I modified its properties in the following way. First, I changed the View property to Details. Then I set MultiSelect property to False. I then set GridLines property and FullRowSelect property to True. I then clicked on three dots in the Columns property field to open up the Columns editor window, and added three Columns ("Title", "First Name", and "Last Name"). In the Events section of the Properties window, I double clicked on the ColumnClick and SelectedIndexChanged events to automatically cerate and link callback methods to those events. Afterwards, I added a GroupBox control and positioned it below the ListView control object on the form, and changed its Text property to have a string value of "Record". Inside it, I added a ComboBox control (having some items in its items collection), and two TextBox controls (one for First Name and one for Last Name), along with some Label controls to help identify them to the user. At the bottom of the Form I added three Button controls (for "New", "Update", and "Delete") and then double clicked each Button control to automatically create and link a callback method to their Click events:

example2

I then altered the Forms source code with the following code. I initialized the forms ListView object with a custom Column Sorter class, and then added two ListViewItems during the Form Load event. I added code to the ListView's ColumnClick events callback method so that whenever the user clicks on one of the Column header's then the custom Sorter class will sort the ListView control object by that Column. I added code to the ListView's SelectedIndexChanged events callback method that whenever the user selects an item then that items values will be displayed in the Form. I then added source code to each of the three Button control objects Click even callback methods, one to create a new record and add it to the ListView, one to update the ListView's selected record, and one to delete the ListView's selected record. I then added a custom method to automatically resize the column widths whenever a record is created, edited, or deleted, and then added a call to it in all of the necessary places throughout the Forms source code. I then added the source code for the custom Sorter class itself and added it to the projects Namespace in the same file as and just below the Forms class:

 
// Copyright 2024 T&J Divisions, LLC	
// All Rights Reserved
using System.Collections;
using System.Windows.Forms;

namespace TestProgram
{
    public partial class Form1 : Form
    {
        private ListViewColumnSorter lvwColumnSorter;

        public Form1()
        {
            InitializeComponent();

            // Create an instance of a ListView column sorter and assign it to the ListView control.
            lvwColumnSorter = new ListViewColumnSorter();
            this.listView1.ListViewItemSorter = lvwColumnSorter;
        }

        void Form1_Load(object sender, EventArgs e)
        {
            // add item #1 to the listview
            ListViewItem newItem1 = new ListViewItem();
            newItem1.Text = "Moderator";
            newItem1.SubItems.Add("Bruce");
            newItem1.SubItems.Add("Wayne");
            listView1.Items.Add(newItem1);

            // add item #2 to the listview
            ListViewItem newItem2 = new ListViewItem();
            newItem2.Text = "Guest";
            newItem2.SubItems.Add("Barry");
            newItem2.SubItems.Add("Allen");
            listView1.Items.Add(newItem2);

            // resize the columns
            resizeColumns();
        }

        private void resizeColumns()
        {
            // Loop through and set each column header width to -2 so that the column will auto-size itself to fit the cell contents.
            foreach (ColumnHeader ch in this.listView1.Columns)
            {
                ch.Width = -2;
            }
        }

        private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // precheck to ensure it has more than 1 item to sort
            if(listView1.Items.Count <= 1) { return; }

            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.listView1.Sort();
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            // init default values
            string title = "";
            string firstName = "";
            string lastName = "";

            // get the values of the selected record
            if(listView1.SelectedItems != null && listView1.SelectedItems.Count > 0)
            {
                title = listView1.SelectedItems[0].SubItems[0].Text;
                firstName = listView1.SelectedItems[0].SubItems[1].Text;
                lastName = listView1.SelectedItems[0].SubItems[2].Text;
            }

            // display them in the Records group box controls
            int itemIndex = cbTitle.Items.IndexOf(title);
            cbTitle.SelectedIndex = itemIndex;
            tbFirstName.Text = firstName;
            tbLastName.Text = lastName;
        }

        private void buttonNew_Click(object sender, EventArgs e)
        {
            // precheck for values
            if(tbFirstName.Text.Trim() == "" && tbLastName.Text.Trim() == "")
            {
                MessageBox.Show(this, "Blank or empty name is not allowed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // instantiate an instance of a new ListViewItem
            ListViewItem newItem = new ListViewItem();

            // set item the values
            newItem.Text = cbTitle.Text;
            newItem.SubItems.Add(tbFirstName.Text);
            newItem.SubItems.Add(tbLastName.Text);

            // add the item to the listview
            listView1.Items.Add(newItem);

            // select just this item in the listview
            listView1.SelectedItems.Clear();
            newItem.Selected = true;

            // resize the columns to auto-fit
            resizeColumns();

        }

        private void buttonUpdate_Click(object sender, EventArgs e)
        {
            // precheck to ensure something is selected
            if (listView1.SelectedItems == null || listView1.SelectedItems.Count == 0)
            {
                MessageBox.Show(this, "You must first select an item to edit", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // precheck for values
            if (tbFirstName.Text.Trim() == "" && tbLastName.Text.Trim() == "")
            {
                MessageBox.Show(this, "Blank or empty name is not allowed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // get index of selected item
            int itemIndex = listView1.SelectedItems[0].Index;

            // update the selected item
            listView1.Items[itemIndex].SubItems[0].Text = cbTitle.Text;
            listView1.Items[itemIndex].SubItems[1].Text = tbFirstName.Text;
            listView1.Items[itemIndex].SubItems[2].Text = tbLastName.Text;

            // resize the columns to auto-fit
            resizeColumns();
        }

        private void buttonDelete_Click(object sender, EventArgs e)
        {
            // precheck to ensure something is selected
            if (listView1.SelectedItems == null || listView1.SelectedItems.Count == 0)
            {
                MessageBox.Show(this, "You must first select an item to delete", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // get index of selected item
            int itemIndex = listView1.SelectedItems[0].Index;

            // remove the item at the specified index
            listView1.Items.RemoveAt(itemIndex);

            // resize the columns to auto-fit
            resizeColumns();
        }

    }


    /// <summary>
    /// This class is an implementation of the 'IComparer' interface,
    /// which we are using to sort the ListView by column.
    /// </summary>
    public class ListViewColumnSorter : IComparer
    {
        // Specifies the column to be sorted
        private int ColumnToSort;

        // Specifies the order in which to sort (i.e. 'Ascending').
        private SortOrder OrderOfSort;

        // Case insensitive comparer object
        private CaseInsensitiveComparer ObjectCompare;

        // Class constructor. Initializes various elements
        public ListViewColumnSorter()
        {
            // Initialize the column to '0'
            ColumnToSort = 0;

            // Initialize the sort order to 'none'
            OrderOfSort = SortOrder.None;

            // Initialize the CaseInsensitiveComparer object
            ObjectCompare = new CaseInsensitiveComparer();
        }

        /// <summary>
        /// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
        /// </summary>
        /// <param name="x">First object to be compared</param>
        /// <param name="y">Second object to be compared</param>
        /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
        public int Compare(object x, object y)
        {
            int compareResult;
            ListViewItem listviewX, listviewY;

            // Cast the objects to be compared to ListViewItem objects
            listviewX = (ListViewItem)x;
            listviewY = (ListViewItem)y;

            // Compare the two items
            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);

            // Calculate correct return value based on object comparison
            if (OrderOfSort == SortOrder.Ascending)
            {
                // Ascending sort is selected, return normal result of compare operation
                return compareResult;
            }
            else if (OrderOfSort == SortOrder.Descending)
            {
                // Descending sort is selected, return negative result of compare operation
                return (-compareResult);
            }
            else
            {
                // Return '0' to indicate they are equal
                return 0;
            }
        }

        /// <summary>
        /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
        /// </summary>
        public int SortColumn
        {
            set
            {
                ColumnToSort = value;
            }
            get
            {
                return ColumnToSort;
            }
        }

        /// <summary>
        /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
        /// </summary>
        public SortOrder Order
        {
            set
            {
                OrderOfSort = value;
            }
            get
            {
                return OrderOfSort;
            }
        }
    }
}

When you run the above example then you should see something similar to the following:


example3

example4

example5

example6

example7

example8


Final Thoughts

Thank you for reading, I hope you found this blog post (tutorial) educational and helpful.


(1) pollYesResult 100%
(0) pollNoResult



 
     About   |   Contact Us   |   Privacy   |   Terms & Conditions   |   © 2024 - T&J Divisions, LLC, All Rights Reserved