I am very new to Visual Studio, and I am working on my first programming assignment. I am having trouble sorting using List<T> and datagridview. I am not receiving any errors, so I am not sure where I am going wrong. Any help or guidance would be appreciated. The column isn't sorting when I click on the header row.
Thanks in advance - Kylee
// Namespaces used
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Web;
using System.Collections;
using System.Reflection;
namespace Test
{
public partial class WoodstockForm : Form
{
public WoodstockForm()
{
InitializeComponent();
}
// Created a variable called StockList
private List<StockType> StockList;
// Save Data
private void SaveData_Click(object sender, EventArgs e)
{
// Uses AppData folder to save alteredstocklist.csv
string appDataFolder = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData
);
string filePath = Path.Combine(appDataFolder, "alteredstocklist.csv");
using (var str = new StreamWriter(filePath))
{
foreach (StockType Stock in StockList)
{
str.WriteLine(Stock);
}
}
}
//Sort column
public class SortableBindingList<T> : BindingList<T>
{
private ArrayList sortedList;
private ArrayList unsortedItems;
private bool isSortedValue;
public SortableBindingList()
{
}
public SortableBindingList(IList<T> list)
{
foreach (object o in list)
{
this.Add((T)o);
}
}
protected override bool SupportsSearchingCore
{
get
{
return true;
}
}
protected override int FindCore(PropertyDescriptor prop, object key)
{
PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
T item;
if (key != null)
{
for (int i = 0; i < Count; ++i)
{
item = (T)Items[i];
if (propInfo.GetValue(item, null).Equals(key))
return i;
}
}
return -1;
}
public int Find(string property, object key)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
PropertyDescriptor prop = properties.Find(property, true);
if (prop == null)
return -1;
else
return FindCore(prop, key);
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override bool IsSortedCore
{
get { return isSortedValue; }
}
ListSortDirection sortDirectionValue;
PropertyDescriptor sortPropertyValue;
protected override void ApplySortCore(PropertyDescriptor prop,
ListSortDirection direction)
{
sortedList = new ArrayList();
Type interfaceType = prop.PropertyType.GetInterface("IComparable");
if (interfaceType == null && prop.PropertyType.IsValueType)
{
Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
if (underlyingType != null)
{
interfaceType = underlyingType.GetInterface("IComparable");
}
}
if (interfaceType != null)
{
sortPropertyValue = prop;
sortDirectionValue = direction;
IEnumerable<T> query = base.Items;
if (direction == ListSortDirection.Ascending)
{
query = query.OrderBy(i => prop.GetValue(i));
}
else
{
query = query.OrderByDescending(i => prop.GetValue(i));
}
int newIndex = 0;
foreach (object item in query)
{
this.Items[newIndex] = (T)item;
newIndex++;
}
isSortedValue = true;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
else
{
throw new NotSupportedException("Cannot sort by " + prop.Name +". This" + prop.PropertyType.ToString() +" does not implement IComparable");
}
}
protected override void RemoveSortCore()
{
int position;
object temp;
if (unsortedItems != null)
{
for (int i = 0; i < unsortedItems.Count; )
{
position = this.Find("LastName",
unsortedItems[i].GetType().
GetProperty("LastName").GetValue(unsortedItems[i], null));
if (position > 0 && position != i)
{
temp = this[i];
this[i] = this[position];
this[position] = (T)temp;
i++;
}
else if (position == i)
i++;
else
unsortedItems.RemoveAt(i);
}
isSortedValue = false;
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
}
public void RemoveSort()
{
RemoveSortCore();
}
protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyValue; }
}
protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionValue; }
}
}
// Import Data
private void ImportData_Click(object sender, EventArgs e)
{
//Create an empty StockList.
this.StockList = new List<StockType>();
//Try/catch is like an if/then statement.
//Try (write to csv), if not the catch
//(message us to let us know what went wrong).
try
{
// Opens directory from current user
string appDataFolder = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData
);
string filePath = Path.Combine(appDataFolder, "stocklist.csv");
using (var reader = new StreamReader(filePath))
{
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = reader.ReadLine()) != null)
{
//Adds a new StockItem in the csv
if (line != "Item Code;Item Description;Current Count;On Order")
StockList.Add(new StockType(line));
}
}
//Connecting to the list to the datagrid
dataGridView1.DataSource = StockList;
// Added sortable list...
SortableBindingList<StockType> sortableList = new SortableBindingList<StockType>(StockList);
BindingSource bs = new BindingSource();
bs.DataSource = sortableList; // Bind to the sortable list
//Only current count is editable
dataGridView1.EditMode = DataGridViewEditMode.EditOnKeystroke;
dataGridView1.Columns["ItemCode"].ReadOnly = true;
dataGridView1.Columns["ItemDescription"].ReadOnly = true;
dataGridView1.Columns["CurrentCount"].ReadOnly = false;
dataGridView1.Columns["OnOrder"].ReadOnly = true;
}
catch (Exception ex)
{
// Let the user know what went wrong.
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.YesNo);
}
}
// Define class StockType
public class StockType : IEquatable<StockType> /*: BindingList<T>*/
{
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
public int CurrentCount { get; set; }
public bool OnOrder { get; set; }
//Constructor
public StockType(string line)
{
try
{
//Splits data into four columns
string[] temp = line.Split(';');
ItemCode = temp[0];
ItemDescription = temp[1];
//int.Parse converts string to int
CurrentCount = int.Parse(temp[2]);
//the csv does not contain text the boolean object can parse, so we check it and use the terneray operator. this has no error checking
OnOrder = (temp[3] == "Yes") ? true : false;
}
catch (Exception ex)
{
MessageBox.Show(line + ex.Message, "Line", MessageBoxButtons.YesNo);
}
}
//Comparison
public int CompareTo(StockType comparison)
{
return this.CurrentCount.CompareTo(comparison.CurrentCount);
}
//Comparison function (equals) - generic object
public override bool Equals(Object obj)
{
if (obj == null) return false;
StockType StockObject = obj as StockType;
if (StockObject == null)
return false;
else
return (this.ItemCode.Equals(StockObject.ItemCode));
}
//Comparison function (equals) - StockType
public bool Equals(StockType other)
{
if (other == null) return false;
return (this.ItemCode.Equals(other.ItemCode));
}
//
public override string ToString()
{
return ItemCode + ";" + ItemDescription + ";" + CurrentCount + ";" + ((OnOrder == true) ? "yes" : "no");
}
//Hashcode??
public override int GetHashCode()
{
return this.ItemCode.GetHashCode();
}
}
}
}