There's not such a built-in way or built-in component for that.
You need to create your own component, or if you want to use DataGridView for that purpose, you can achieve it by writing custom code. Here I've achieved that using a custom TypeDescriptor.
Type descriptor provide information about type, including list of properties and getting and setting property values. DataTable
also works the same way, to show list of columns in DataGridView, it returns a list of property descriptors containing properties per column. Here I've used such technique.
As you can see in the screen capture, when you edit the rotated list, you are actually editing the original list:
//Set Data Source
dgv.DataSource = new RotatedListDataSource<Employee>(list);
//Hide Column Headers
dgv.ColumnHeadersVisible = false;
//Set Row Headers Autosize
dgv.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
//Show PropertyName on RowHeader
dgv.RowPrePaint += (o, a) =>
{
var value = ((RotatedItem)dgv.Rows[a.RowIndex].DataBoundItem).PropertyName;
if (a.RowIndex > -1 && $"{dgv.Rows[a.RowIndex].HeaderCell.Value}" != value)
dgv.Rows[a.RowIndex].HeaderCell.Value = value;
};
If you liked the idea and what to give it a try for learning purpose to see how type descriptor works, here is the code for type descriptor and property descriptors that I created:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
public class RotatedListDataSource<T> : List<RotatedItem>
{
public List<T> List { get; }
public RotatedListDataSource(List<T> list)
{
List = list;
this.AddRange(typeof(T).GetProperties().Select(p =>
new RotatedItem(
p.Name,
list.Cast<object>().ToArray(),
p.PropertyType)));
}
}
public class RotatedItem : CustomTypeDescriptor
{
public string PropertyName { get; }
private object[] data;
public Type Type { get; }
public RotatedItem(string propertyName, object[] data, Type type)
{
this.PropertyName = propertyName;
this.data = data;
this.Type = type;
}
public override PropertyDescriptorCollection GetProperties()
{
return this.GetProperties(new Attribute[] { });
}
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var properties = new List<PropertyDescriptor>();
properties.Add(new PropertyNameProperty(new Attribute[] {
new BrowsableAttribute(false)}));
for (int i = 0; i < data.Length; i++)
{
properties.Add(new IndexProperty(i, typeof(object), new Attribute[] { }));
}
return new PropertyDescriptorCollection(properties.ToArray());
}
public object this[int i]
{
get => data[i].GetType().GetProperty(PropertyName).GetValue(data[i]);
set => data[i].GetType().GetProperty(PropertyName).SetValue(
data[i], Convert.ChangeType(value, Type));
}
}
public class IndexProperty : PropertyDescriptor
{
int index;
Type type;
public IndexProperty(int index, Type type, Attribute[] attributes)
: base(index.ToString(), attributes)
{
this.index = index;
this.type = type;
}
public override Type ComponentType => typeof(RotatedItem);
public override bool IsReadOnly => false;
public override Type PropertyType => type;
public override bool CanResetValue(object component) => false;
public override object GetValue(object component) =>
((RotatedItem)component)[index];
public override void ResetValue(object component) { }
public override void SetValue(object component, object value) =>
((RotatedItem)component)[index] = value;
public override bool ShouldSerializeValue(object component) => true;
}
public class PropertyNameProperty : PropertyDescriptor
{
public PropertyNameProperty(Attribute[] attributes)
: base(nameof(RotatedItem.PropertyName), attributes) { }
public override Type ComponentType => typeof(RotatedItem);
public override bool IsReadOnly => true;
public override Type PropertyType => typeof(string);
public override bool CanResetValue(object component) => false;
public override object GetValue(object component) =>
((RotatedItem)component).PropertyName;
public override void ResetValue(object component) { }
public override void SetValue(object component, object value) { }
public override bool ShouldSerializeValue(object component) => true;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…