How to: Implement the ITypedList Interface
.NET Framework 4.5
Implement the ITypedList interface to enable discovery of the schema for a bindable list.
The following code example demonstrates how to implement the ITypedList interface. A generic type named SortableBindingList derives from the BindingList class and implements the ITypedList interface. A simple class named Customer provides data, which is bound to the header of a DataGridView control.
using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Windows.Forms; using System.Collections; using System.Reflection; namespace ITypedListCS { [Serializable()] public class SortableBindingList<T> : BindingList<T>, ITypedList { [NonSerialized()] private PropertyDescriptorCollection properties; public SortableBindingList() : base() { // Get the 'shape' of the list. // Only get the public properties marked with Browsable = true. PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties( typeof(T), new Attribute[] { new BrowsableAttribute(true) }); // Sort the properties. properties = pdc.Sort(); } #region ITypedList Implementation public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) { PropertyDescriptorCollection pdc; if (listAccessors!=null && listAccessors.Length>0) { // Return child list shape. pdc = ListBindingHelper.GetListItemProperties(listAccessors[0].PropertyType); } else { // Return properties in sort order. pdc = properties; } return pdc; } // This method is only used in the design-time framework // and by the obsolete DataGrid control. public string GetListName(PropertyDescriptor[] listAccessors) { return typeof(T).Name; } #endregion } }
using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; namespace ITypedListCS { class Customer : INotifyPropertyChanged { public Customer() {} public Customer(int id, string name, string company, string address, string city, string state, string zip) { this._id = id; this._name = name; this._company = company; this._address = address; this._city = city; this._state = state; this._zip = zip; } #region Public Properties private int _id; public int ID { get { return _id; } set { if (_id != value) { _id = value; OnPropertyChanged(new PropertyChangedEventArgs("ID")); } } } private string _name; public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged(new PropertyChangedEventArgs("Name")); } } } private string _company; public string Company { get { return _company; } set { if (_company != value) { _company = value; OnPropertyChanged(new PropertyChangedEventArgs("Company")); } } } private string _address; public string Address { get { return _address; } set { if (_address != value) { _address = value; OnPropertyChanged(new PropertyChangedEventArgs("Address")); } } } private string _city; public string City { get { return _city; } set { if (_city != value) { _city = value; OnPropertyChanged(new PropertyChangedEventArgs("City")); } } } private string _state; public string State { get { return _state; } set { if (_state != value) { _state = value; OnPropertyChanged(new PropertyChangedEventArgs("State")); } } } private string _zip; public string ZipCode { get { return _zip; } set { if (_zip != value) { _zip = value; OnPropertyChanged(new PropertyChangedEventArgs("ZipCode")); } } } #endregion #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { if (null != PropertyChanged) { PropertyChanged(this, e); } } #endregion } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace ITypedListCS { public partial class Form1 : Form { private SortableBindingList<Customer> sortableBindingListOfCustomers; private BindingList<Customer> bindingListOfCustomers; private System.ComponentModel.IContainer components = null; private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private System.Windows.Forms.Label label2; private DataGridView dataGridView1; private Button button1; private Button button2; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { this.sortableBindingListOfCustomers = new SortableBindingList<Customer>(); this.bindingListOfCustomers = new BindingList<Customer>(); this.dataGridView1.DataSource = this.bindingListOfCustomers; } private void button1_Click(object sender, EventArgs e) { this.dataGridView1.DataSource = null; this.dataGridView1.DataSource = this.sortableBindingListOfCustomers; } private void button2_Click(object sender, EventArgs e) { this.dataGridView1.DataSource = null; this.dataGridView1.DataSource = this.bindingListOfCustomers; } protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.label2 = new System.Windows.Forms.Label(); this.dataGridView1 = new System.Windows.Forms.DataGridView(); this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.flowLayoutPanel1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); this.SuspendLayout(); // // flowLayoutPanel1 // this.flowLayoutPanel1.AutoSize = true; this.flowLayoutPanel1.Controls.Add(this.label2); this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top; this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; this.flowLayoutPanel1.Size = new System.Drawing.Size(566, 51); this.flowLayoutPanel1.TabIndex = 13; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(3, 6); this.label2.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(558, 39); this.label2.TabIndex = 0; this.label2.Text = "This sample demonstrates how to implement the ITypedList interface. Clicking on the 'Sort Columns' button will bind the DataGridView to a sub-classed BindingList<T> that implements ITypedList to provide a sorted list of columns. Clicking on the 'Reset' button will bind the DataGridView to a normal BindingList<T>."; // // dataGridView1 // this.dataGridView1.AllowUserToAddRows = false; this.dataGridView1.AllowUserToDeleteRows = false; this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.Location = new System.Drawing.Point(6, 57); this.dataGridView1.Name = "dataGridView1"; this.dataGridView1.ReadOnly = true; this.dataGridView1.RowHeadersVisible = false; this.dataGridView1.Size = new System.Drawing.Size(465, 51); this.dataGridView1.TabIndex = 14; // // button1 // this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.button1.Location = new System.Drawing.Point(477, 57); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(82, 23); this.button1.TabIndex = 15; this.button1.Text = "Sort Columns"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // button2 // this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.button2.Location = new System.Drawing.Point(477, 86); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(82, 23); this.button2.TabIndex = 16; this.button2.Text = "Reset"; this.button2.UseVisualStyleBackColor = true; this.button2.Click += new System.EventHandler(this.button2_Click); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(566, 120); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Controls.Add(this.dataGridView1); this.Controls.Add(this.flowLayoutPanel1); this.Name = "Form1"; this.Text = "ITypedList Sample"; this.Load += new System.EventHandler(this.Form1_Load); this.flowLayoutPanel1.ResumeLayout(false); this.flowLayoutPanel1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion } static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }