Sortable BindingList for custom column - c#

I have a DataGridView which is data-bound to a BindingList. My DataGridView also has a couple of custom columns that I have added. These are not data-bound, but rather are generated based on items in my BindingList
(ie: an item in my BindingList of type A has a property of type B; my custom column shows B.Name
In this case, "Name" is a property of class B, and thus the property represented by the column is not directly found in the items in the BindingList).
Can anyone help me for this?
I wanted to make it generic.
e.g.
public class Fruits
{
public String Id {get;set}
public String Name {get;set}
}
public class People
{
public String ID {get;set}
public String Name {get;set}
public Fruits FavouriteFruit{get;set}
}
In BindingList as we can do sorting using custom sortable list for the properties on People, in the DatagridView but, I also wanted to sort People based on the FavouriteFruit.

You can inherit DataGRidView and add the required properties.

Related

Show ToString of a Collection Wrapper Class in DataGridView

I have a class that has one of its properties being of type ObservableCollection<string>
public class SizeList
{
public string ID { get; set; }
public string Name { get; set; }
//public ObservableCollection<string> List { get; set; }
public ListEntryCollection List { get; set; }
}
During a unit test I return a list of SizeList and then show it in a DataGridView to check the results I am expecting, the data is fine but I am missing the field List in the DGV; only the ID and Name are shown, so I have made a wrapper class for the ObservableCollection<string> and overriden its .ToString() method:
namespace System.Collections.ObjectModel
{
using System.Collections.Generic;
public class ListEntryCollection : ObservableCollection<string>
{
public ListEntryCollection(IEnumerable<string> collection)
: base(collection)
{
}
public override string ToString()
{
return Count.ToString() + ((Count > 1) ? " Entries": " Entry");
}
}
}
But I am still not getting the List field in the DGV, so what am I doing wrong ?
Per Column Types in the Windows Forms DataGridView Control, the only property types for which bound columns are automatically generated are numbers, text, booleans, and images.
To display other types, you need to add the column manually to the DataGridView, or use a custom column type (and even then, you'll probably have to add it manually.)
A couple of options present themselves:
You could try adding a read-only property to SizeList to display the description of the list, and see if that will result in a column being automatically created.
You can try adding a column manually, which I believe you can do in the Form Designer if you click on the DataGridView. You will probably have to override a method or two, or use an event handler, in order to change the display from the default. (It's possible, though, that it will use the ToString override you created, in which case the problem is solved.)
Or, you could create a ListSummaryDataGridViewColumn class, that can represent a list by display a count of the items in it, and add one of those manually.

How do you combine the values of a property from multiple objects

i have a class that has a property that has the Mergeable attribute applied to it.
public class MyObject
{
[MergableProperty(true)]
public double Time{get; set;}
}
When i select multiple of these objects and send them into a propertygrid i want the property grid to show the combined values of the selected objects for that property. How to you handle the Merge Attribute?

Binding the value of an object's property to a data bound ComboBox in .NET WinForms

Currently building a WinForms data collection tool using C# and have been able to implement the binding of the values of my underling object/entity's properties to controls on the my form, e.g. TextBoxes, MaskedTextBoxes and Checkboxes to properties on my domain model class (e.g. Person class). However, I have not been able to do this binding successfully with the ComboBox control.
With my Person class looking basically like this:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Gender { get; set; }
}
I am using the ComboBox's DataSource property to bind to a Dictionary and setting the ValueMember and DisplayMember accordingly. Doing so successfully populates that ComboBox with my reference data (display value and coded value) at run-time.
Dictionary<int, string> genderValues = repository.GetGenderValues()
cboGender.DataSource = new BindingSource(genderValues, null);
cboGender.ValueMember = "Key";
cboGender.DisplayMember = "Value";
However, when I try to bind my Person object's property 'Gender' to this ComboBox, following the pattern that worked with other control types (TextBox, CheckBox, etc.)
cboGender.DataBindings.Add(new Binding("ValueMember", _currentPerson, "Gender"));
The value of Gender on my person object is always NULL even after selecting an item in the Gender ComboBox. Perhaps I am overlooking an additional step needed for binding the ValueMember of a ComboBox to a object property?
ValueMember is a string and it does not change with a different selection in the combobox. You need to use one of the Selected... properties. Since it's an int, use SelectedValue.
Maybe this will help:
cboGender.DataBindings.Add("SelectedIndex", genderValues, "Value", false, DataSourceUpdateMode.OnPropertyChanged);

Bind winforms datagridview rowheader

In C# Winforms DataGridView I am binding a List of class using the datagriview's datasource property. Is there a way to bind one of the class property to the datagriview's rowheader?
I didn't want to iterate all the rows and add row header values one by one because I will have thousands of records so I wanted the rowheader to get the values from the binded class when I set the datasource.
For example I have this class and I want the rowheaders to show the Customer ID.
private class Customer
{
public string CustomerID { get; set; }
public string CustomerFirstName { get; set; }
}
I'm afraid you have to implement datagridview's OnPaint-Method, where you paint the customer id in a loop. Once, I wanted to numerate my entries and I didn't find any other solution.

Binding Custom List Property To DatagridView

I have a problem that is difficult to explain. Essentially I have a list of a certain class we can call MyObj. One of the properties of this object is a custom list itself. I would like to bind this List to a dataGridView and have this particular property that is also a list show up. Any ideas? Am I being clear enough? :-P..
Here is the idea. I have my own custom list object overriding the ToString() method:
public class CategoriesList : List<Category>
{
public override string ToString()
{...}
}
This is used as a property in an object such as:
public MyObj
{
public string Property1 {get; set; }
public string Property2 {get; set; }
public CategoriesList Categories {get; set; }
}
In turn, I have a list of these objects such as:
List<MyObj> myDataSouce = SomeRepository.GetMyObjList();
Where I bind this to a datagrid view:
MyDataGridView.DataSource = myDataSource;
Property1 and Property2 are automatically generated. Is there any way to have the CategoriesList property be added as well? I previously thought Overriding the ToString() method on a class would be enough..
I am really lost on this one as I have no idea how to even google for it :-P
Assuming that you'd like to display a specific value in place of the list in the datagridview, you'll want to use a custom TypeConverter. Otherwise you'll need to place a control in the datagridview column that supports lists, like a drop down list and bind to that.
For the former:
Basically decorate your categories property with a custom typeconverter:
[TypeConverter(typeof(MyConverter))]
public CategoriesList Categories { get; set; }
Then use a custom type converter that basically tells the datagrid that when it encounters the categories property what do display:
public class MyConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is CategoriesList) {
return value.ToString();
}
return base.ConvertFrom(context, culture, value);
}
}
You'll need to add your column to be databound manually by adding an unbound column and specify the DataPropertyName for the property to be mapped to that column, in this case "Categories"
If you're looking to display second level properties as well then this may help:
http://blogs.msdn.com/b/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx
This might help... look at my answer there, I haven't tried it with a property that is also a type of list but I think the idea is the same.
Or this one as well, I also have an answer there with a sample code too...

Categories