Plunging into .NET Development

Weblog Pieter Gheysens
Microsoft .NET Development - C# - Enterprise Library - Visual Studio 2005 Team System - Compuware DevPartner - ...
 


Thursday, January 13

DataBinding DataSet to ListView

Why do I want to databind a ListView-control and not use the DataGrid-control? Well, I think that the ListView-control is more suitable for displaying readonly data and the look and feel is also customizable (see previous post). I regret that DataBinding is not possible for the base ListView-control ...

.NET allows us to create custom controls by using inheritance. In my example I will inherit from the ListView-control and add functionality to this base control to create a custom databound ListView-control.



In the form above a listView is used for displaying all data (stored in a dataset "MyDataSet") and Textboxes are set for updating the data. Binding Textboxes to a dataset is simple :

            //DataBinding for TextBoxes

            this.txtFirstName.DataBindings.Add("Text", this.myDataSet.Names, "FirstName");

            this.txtLastName.DataBindings.Add("Text", this.myDataSet.Names, "LastName");


Binding more complex controls is done via the DataSource property :

                //DataBinding for DataGrid

                this.myDataGrid.DataSource = myDataSet.Names;


So for building a Databound ListView we need to implement a custom DataSource Property [+ DataMember for name of DataTable] and focus on the interaction with the DataSource to retrieve the data for display (DataBinding) in the listView.

I've created a separate project for storing the new databound ListView. In the constructor some defaults are already set for my ListView and I've also created two Properties (DataSource and DataMember).

using System;

using System.Data;

using System.Drawing;

using System.Windows.Forms;

using System.Collections;

 

namespace DataBoundListView

{

    public class MyListView : ListView

    {

        //Variables

        private string dataMember;

        private DataSet dataSource;

        private int columnWidth = 100;

        private CurrencyManager cm;

 

        //Constructor

        public MyListView()

        {

            //set default settings for listView

            this.View = View.Details;

            this.FullRowSelect = true;

            this.MultiSelect = false;

            this.BackColor = Color.Wheat;

            this.ForeColor = Color.Brown;

            this.HideSelection = false;

 

            this.SelectedIndexChanged += new EventHandler(MyListView_SelectedIndexChanged);

        }

 

        //Properties

        public string DataMember

        {

            get { return this.dataMember; }

            set { this.dataMember = value; }

        }

 

        public DataSet DataSource

        {

            get { return this.dataSource; }

            set

            {

                this.dataSource = value;

                this.dataBindControl();

                this.setCurrencyManager();

            }

        }

 

        //Methods

        private void setCurrencyManager()

        {

            //Assign CurrencyManager [from BindingContext]

            this.cm = (CurrencyManager) this.BindingContext[this.dataSource.Tables[dataMember]];

        }

 

        private void dataBindControl()

        {

            this.Clear();

 

            ListViewItem newItem;

 

            //Add columns to ListView

            foreach (DataColumn col in this.dataSource.Tables[dataMember].Columns)

            {

                base.Columns.Add(col.ColumnName, columnWidth, HorizontalAlignment.Left);

            }

 

            for (int i=0; i < this.dataSource.Tables[dataMember].Rows.Count; i++)

            {

                newItem = new ListViewItem();

                //First Column

                newItem.Text = this.dataSource.Tables[dataMember].Rows[i].ItemArray[0].ToString();

                //SubItems

                for (int subItems=1; subItems < base.Columns.Count; subItems++)

                {

                    newItem.SubItems.Add(this.dataSource.Tables[dataMember].Rows[i].ItemArray[subItems].ToString());

                }

 

                this.Items.Add(newItem);

            }

        }

 

        private void MyListView_SelectedIndexChanged(object sender, EventArgs e)

        {

            if (this.SelectedItems.Count > 0)

            {

                //set Position of CurrencyManager to selectedIndex of ListView

                cm.Position = this.SelectedItems[0].Index;

            }

        }

    }

}


In the method "dataBindControl", the databinding is set for the dataSet. First, the columns are added to the listView and afterwards, the rows (item + subItems) are added. This method is called each time the "DataSource" Property is set. "setCurrencyManager" assigns the CurrencyManager and the EventHandler "MyListView_SelectedIndexChanged" sets the position of the CurrencyManager so that other controls bound to myDataSet can be updated.

That's all for coding the custom ListView. The control is now ready to use in a new project ...

            //Using the custom control

            this.myListView = new MyListView();

            this.myListView.DataMember = "Names";

            this.myListView.DataSource = this.myDataSet;


The EventHandlers of the textBoxes are looking after the DataBinding with myDataSet and so for updating the ListView.

        private void txtFirstName_Validated(object sender, System.EventArgs e)

        {

            this.renewDataBinding();

        }

 

        private void txtLastName_Validated(object sender, System.EventArgs e)

        {

            this.renewDataBinding();

        }

 

        private void renewDataBinding()

        {

            this.myListView.DataSource = this.myDataSet;

        }


Useful links

2 Comments:

  • At 10:45 AM, Anonymous Pete said…

    are you sure, that this works? i've tried your code, but it doesn't work.

    "foreach (DataColumn col in this.dataSource.Tables[dataMember].Columns)
    {" is complaining about a
    NullReferenceException...

     
  • At 6:38 PM, Anonymous Anonymous said…

    It works. Just remember to set the datamember to the name of the table you want to show.

     

Post a Comment

Links to this post:

Create a Link

<< Home