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(); } } } }