Need Help Determining DataGrid Column Selected for Sort using IBindingList - Datagrid.zip (0/1)

D

David Elliott

I have a Collection that inherits from CollectionBase and Implements IBindingList which I have bound
to a DataGrid. So far everything works fine.

However, I am missing one piece to the IBindingList that I haven't figured out yet, how to determine
which DataGrid column header I clicked on so I can do a custom sort. Right now the sort is rotating
just to see that everything works.

There are two pieces of the IBindingList that I didn't know what to do with
PropertyDescriptor returned from IBindingList.SortProperty
ListChanged
What is the intent of these two items?

I have attached a small demo app that I have been working with. As a side note, I haven't been able
to get the DataGridTableStyle to work either.

The IBindingList implementation is in MyCollection.cs
The DataGridTableStyle implementation is in Form1.cs

Any thoughts are appreciated.

Dave
(e-mail address removed)
 
D

David Elliott

Inlining files...

I have a Collection that inherits from CollectionBase and Implements IBindingList which I have bound
to a DataGrid. So far everything works fine.

However, I am missing one piece to the IBindingList that I haven't figured out yet, how to determine
which DataGrid column header I clicked on so I can do a custom sort. Right now the sort is rotating
just to see that everything works.

There are two pieces of the IBindingList that I didn't know what to do with
PropertyDescriptor returned from IBindingList.SortProperty
ListChanged
What is the intent of these two items?

I have attached a small demo app that I have been working with. As a side note, I haven't been able
to get the DataGridTableStyle to work either.

The IBindingList implementation is in MyCollection.cs
The DataGridTableStyle implementation is in Form1.cs

Any thoughts are appreciated.

Dave
(e-mail address removed)


=======================================================
Form1.cs
=======================================================

using System;
using System.Drawing;
using System.Windows.Forms;

namespace DataGrid
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
MyCollection mycoll;
private System.Windows.Forms.DataGrid dataGrid1;

/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
CreateCollection();

CreateDataGrid();
dataGrid1.SetDataBinding(mycoll, "");
}

/// <summary>
///
/// </summary>
public void CreateDataGrid()
{
//Create a DataTable style object
DataGridTableStyle ts1 = new DataGridTableStyle();
ts1.MappingName = "tableStyle1";
ts1.AlternatingBackColor = Color.LightBlue;

// Column 1
DataGridColumnStyle boolCol = new DataGridBoolColumn();
boolCol.MappingName = "select";
boolCol.HeaderText = "SELECT THIS";
boolCol.Width = 70;
((DataGridBoolColumn)boolCol).AllowNull = false;
ts1.GridColumnStyles.Add(boolCol);

// Column 2
DataGridColumnStyle TextCol = new DataGridTextBoxColumn();
TextCol.ReadOnly = true;
TextCol.MappingName = "company";
TextCol.HeaderText = "MY COMPANY";
TextCol.Width = 100;
ts1.GridColumnStyles.Add(TextCol);

// Column 3
DataGridColumnStyle TextCol2 = new DataGridTextBoxColumn();
TextCol2.ReadOnly = true;
TextCol2.MappingName = "state";
TextCol2.HeaderText = "MY STATE";
TextCol2.Width = 100;
ts1.GridColumnStyles.Add(TextCol2);

// Add ColumnStyle to DataGrid
dataGrid1.TableStyles.Add(ts1);
}

/// <summary>
///
/// </summary>
public void CreateCollection()
{
mycoll = new MyCollection();
mycoll.Add(new Job(false, "Programmer", "Boeing", "Raleigh", "NC"));
mycoll.Add(new Job(false, "Analyst", "Intel", "Durham", "NC"));
mycoll.Add(new Job(false, "Programmer", "Microsoft","Raleigh", "NC"));
mycoll.Add(new Job(false, "DBA", "Redhat", "Tampa", "FL"));
mycoll.Add(new Job(false, "Analyst", "Redhat", "Raleigh", "NC"));
mycoll.Add(new Job(false, "DBA", "Micorosft","Durham", "NC"));
mycoll.Add(new Job(false, "Programmer", "Intel", "Tampa", "FL"));
mycoll.Add(new Job(false, "Analyst", "Boeing", "Durham", "NC"));
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.dataGrid1 = new System.Windows.Forms.DataGrid();
((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
this.SuspendLayout();
//
// dataGrid1
//
this.dataGrid1.DataMember = "";
this.dataGrid1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
this.dataGrid1.Name = "dataGrid1";
this.dataGrid1.Size = new System.Drawing.Size(552, 366);
this.dataGrid1.TabIndex = 5;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(552, 366);
this.Controls.AddRange(new System.Windows.Forms.Control[] {

this.dataGrid1});
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}

=======================================================
Job.cs
=======================================================

using System;


namespace DataGrid
{

/// <summary>
/// Summary description for Clastitle.
/// </summary>
public class Job
{
private bool m_select;
private string m_title;
private string m_company;
private string m_city;
private string m_state;

public Job (bool select, string title, string company,
string city, string state)
{
m_select = select;
m_title = title;
m_company = company;
m_city = city;
m_state = state;
}

public bool select { get {return m_select;} set {m_select = value;}}
public string title { get {return m_title;} set {m_title = value;}}
public string company { get {return m_company;} set {m_company = value;}}
public string city { get {return m_city;} set {m_city = value;}}
public string state { get {return m_state;} set {m_state = value;}}
}
}


=======================================================
SortClass.cs
=======================================================

using System;
using System.Collections;

namespace DataGrid
{
/// <summary>
///
/// </summary>
public enum SortByFlags
{
sortPostDate,
sortState,
sortTitle,
sortCompany
}

/// <summary>
///
/// </summary>
public abstract class JobRecordSortFactory : IComparer
{
public static IComparer Create(SortByFlags sortBy)
{
IComparer tempIComparer = null;
switch (sortBy)
{
case SortByFlags.sortPostDate:
break;
case SortByFlags.sortState:
tempIComparer = new JobRecordSortState();
break;
case SortByFlags.sortTitle:
tempIComparer = new JobRecordSortTitle();
break;
case SortByFlags.sortCompany:
tempIComparer = new JobRecordSortCompany();
break;
}

return (tempIComparer);
}

/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
int IComparer.Compare(object x, object y)
{
return (returnSort(x, y));
}

protected abstract int returnSort(object x, object y);
}

/// <summary>
/// Sort by:
/// 1) State
/// 2) City
/// 3) Job Title
/// 4) Postdate

/// </summary>
public class JobRecordSortState : JobRecordSortFactory
{
protected override int returnSort(object x, object y)
{
int rc;
Job rec1 = x as Job;
Job rec2 = y as Job;

if (x.GetType() != y.GetType())
throw new ArgumentException("Invalid comparison");

CaseInsensitiveComparer aComparer = null;
aComparer = new CaseInsensitiveComparer();


if ((rc = aComparer.Compare(rec1.state, rec2.state)) == 0)
{
if ((rc = aComparer.Compare(rec1.city, rec2.city)) == 0)
rc = aComparer.Compare(rec1.title, rec2.title);
}

return (rc);
}
}

/// <summary>
/// Sort by:
/// 1) Job Title
/// 2) Postdate
/// 3) State
/// 4) City
/// </summary>
public class JobRecordSortTitle : JobRecordSortFactory
{
protected override int returnSort(object x, object y)
{
int rc;
Job rec1 = x as Job;
Job rec2 = y as Job;

if (x.GetType() != y.GetType())
throw new ArgumentException("Invalid comparison");

CaseInsensitiveComparer aComparer = null;
aComparer = new CaseInsensitiveComparer();

if ((rc = aComparer.Compare(rec1.title, rec2.title)) == 0)
{
if ((rc = aComparer.Compare(rec1.state, rec2.state)) == 0)
rc = aComparer.Compare(rec1.city, rec2.city);
}

return (rc);
}
}

/// <summary>
/// Sort by:
/// 1) Company
/// 2) State
/// 3) City
/// 4) Job Title
/// 5) Postdate
/// </summary>
public class JobRecordSortCompany : JobRecordSortFactory
{
protected override int returnSort(object x, object y)
{
int rc;
Job rec1 = x as Job;
Job rec2 = y as Job;

if (x.GetType() != y.GetType())
throw new ArgumentException("Invalid comparison");

CaseInsensitiveComparer aComparer = null;
aComparer = new CaseInsensitiveComparer();

if ((rc = aComparer.Compare(rec1.company, rec2.company)) == 0)
{
if ((rc = aComparer.Compare(rec1.state, rec2.state)) == 0)
{
if ((rc = aComparer.Compare(rec1.city, rec2.city)) == 0)
rc = aComparer.Compare(rec1.title, rec2.title);
}
}

return (rc);
}
}
}

=======================================================
MyCollection.cs
=======================================================
using System;
using System.Data;
using System.Collections;
using System.ComponentModel;

namespace DataGrid
{
/// <summary>
/// Summary description for MyCollection.
/// </summary>
public class MyCollection : CollectionBase, IBindingList
{
#region MyCollection Methods

/// <summary>
///
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
public int Add(Job c)
{
return base.InnerList.Add(c);
}

/// <summary>
///
/// </summary>
public Job this[int idx]
{
get { return (Job)base.InnerList[idx]; }
set { base.InnerList[idx] = value; }
}

/// <summary>
///
/// </summary>
/// <param name="sorter"></param>
public void Sort(IComparer sorter)
{
base.InnerList.Sort(sorter);
}
#endregion

//
// IBindingList Implementation
//

#region IBindingList Class Members
private PropertyDescriptor sortProperty;
private ListSortDirection sortDirection = ListSortDirection.Ascending;
private int sortagain = 0;
#endregion

#region Events
// Events.
public event ListChangedEventHandler ListChanged {add{} remove{}}
#endregion

#region Properties
// Properties

bool IBindingList.AllowEdit { get { return true; }}
bool IBindingList.AllowNew { get { return false; }}
bool IBindingList.AllowRemove { get { return false; }}
bool IBindingList.IsSorted { get { return true; }}
ListSortDirection IBindingList.SortDirection { get { return sortDirection;}}
PropertyDescriptor IBindingList.SortProperty { get { return sortProperty;}}
bool IBindingList.SupportsChangeNotification { get { return false; }}
bool IBindingList.SupportsSearching { get { return false; }}
bool IBindingList.SupportsSorting { get { return true; }}

#endregion

#region Supported Methods

// Methods.
void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
{
IComparer sorter = null;


if (++sortagain > 3)
sortagain = 1;

switch (sortagain)
{
case 1:
sorter = JobRecordSortFactory.Create(SortByFlags.sortState);
break;
case 2:
sorter = JobRecordSortFactory.Create(SortByFlags.sortCompany);
break;
case 3:
sorter = JobRecordSortFactory.Create(SortByFlags.sortTitle);
break;
}

if (sorter != null)
this.Sort(sorter);
}
#endregion

#region Unsupported Methods
// Unsupported Methods.
void IBindingList.AddIndex(PropertyDescriptor property)
{throw new NotSupportedException();}
object IBindingList.AddNew()
{throw new NotSupportedException();}
int IBindingList.Find(PropertyDescriptor property, object key)
{throw new NotSupportedException();}
void IBindingList.RemoveIndex(PropertyDescriptor property)
{throw new NotSupportedException();}
void IBindingList.RemoveSort()
{throw new NotSupportedException();}
#endregion
}
}


=======================================================
Form1.resx
=======================================================

<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema

Version 1.3

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>

There are any number of "resheader" rows that contain simple
name/value pairs.

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="$this.Name">
<value>Form1</value>
</data>
</root>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top