I am trying to implement Linda Liu's solution for displaying second-level properties in a DataGridView. If I'm understanding everything correctly, when a DataSource is set, C# uses a method called ICustomTypeDescriptor.GetProperties, which "grabs" PropertyDescriptors from the class module and adds them to a collection. So Liu's solution is to create PropertyDescriptors for the second level properties and to return them along with the original PropertyDescriptors.
In my case, EmployeeModel has a property JobTitle. JobTitle has properties Name and ID. My SQL joins these and returns a list of EmployeeModel with JobTitle.Name and JobTitle.ID set. I want to display JobTitle.Name as a column in EmployeeGridView. (When I've managed to make this work, I'll do the same for several other properties of EmployeeModel.)
Everything compiles, but at runtime the effect is not achieved. I end up with an extra column with no visible content, while the original JobTitle column is replicated as the rightmost column.
Screenshot of my application
namespace WorkDesk_Library.Binding_Assist
{
class MyTypeDescriptionProvider : TypeDescriptionProvider
{
private ICustomTypeDescriptor td;
public MyTypeDescriptionProvider()
: this(TypeDescriptor.GetProvider(typeof(EmployeeModel)))
{
}
public MyTypeDescriptionProvider(TypeDescriptionProvider parent)
: base(parent)
{
}
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
if (td == null)
{
td = base.GetTypeDescriptor(objectType, instance);
td = new MyCustomTypeDescriptor(td);
}
return td;
}
}
}
namespace WorkDesk_Library.Binding_Assist
{
class MyCustomTypeDescriptor : CustomTypeDescriptor
{
public MyCustomTypeDescriptor(ICustomTypeDescriptor parent)
: base(parent)
{
}
public override PropertyDescriptorCollection GetProperties()
{
PropertyDescriptorCollection cols = base.GetProperties();
PropertyDescriptor JobTitle = cols["JobTitle"];
PropertyDescriptorCollection JobTitle_child = JobTitle.GetChildProperties();
PropertyDescriptor[] array = new PropertyDescriptor[cols.Count + 2];
cols.CopyTo(array, 0);
array[cols.Count] = new SubPropertyDescriptor(JobTitle, JobTitle_child["Name"], "JobTitle_Name");
array[cols.Count + 1] = new SubPropertyDescriptor(JobTitle, JobTitle_child["ID"], "JobTitle_ID");
PropertyDescriptorCollection newcols = new PropertyDescriptorCollection(array);
return newcols;
}
}
}
namespace WorkDesk_Library.Interfaces
{
class SubPropertyDescriptor : PropertyDescriptor
{
private PropertyDescriptor _subPD;
private PropertyDescriptor _parentPD;
public SubPropertyDescriptor(PropertyDescriptor parentPD, PropertyDescriptor subPD, string pdname)
: base(pdname, null)
{
_subPD = subPD;
_parentPD = parentPD;
}
public override Type ComponentType
{
get { return _parentPD.ComponentType; }
}
public override bool IsReadOnly { get { return false; } }
public override Type PropertyType
{
get { return _subPD.PropertyType; }
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return _subPD.GetValue(_parentPD.GetValue(component));
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
_subPD.SetValue(_parentPD.GetValue(component), value);
OnValueChanged(component, EventArgs.Empty);
}
public override bool ShouldSerializeValue(object component)
{
return true;
}
}
}
public void CreateEmployeeTable()
{
EmployeeGridView.DataSource = globalEmployeeList;
EmployeeGridView.Columns[0].HeaderText = "Employee ID";
EmployeeGridView.Columns["ID"].DisplayIndex = 0;
EmployeeGridView.Columns["ListView"].DisplayIndex = 1;
EmployeeGridView.Columns["ListView"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
EmployeeGridView.Columns["Department"].DisplayIndex = 2;
EmployeeGridView.Columns["JobTitle"].DisplayIndex = 3;
EmployeeGridView.Columns["JobTitle"].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
EmployeeGridView.Columns["Nickname"].Visible = false;
EmployeeGridView.Columns["FirstName"].Visible = false;
EmployeeGridView.Columns["LastName"].Visible = false;
EmployeeGridView.Columns["HireDate"].Visible = false;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…