Как я понимаю вопрос, у вас есть DataGridView
с AutoGenerateColumns=true
, просто установите DataSource
недвижимость DataTable
и хочет, чтобы иметь возможность настроить автогенерируемую столбцы.
Позвольте мне начать с того, что это невозможно. DataGridView
не предоставляет какой-либо способ настройки автоматически сгенерированных столбцов - никакого события, виртуального метода, атрибута и т. Д. Это все или ничего. А по умолчанию он создает только три типа колонн - флажки, изображение и текст, с чем-то вроде этого:
private static DataGridViewColumn DefaultColumnFactory(Type type)
{
if (type == typeof(bool)) return new DataGridViewCheckBoxColumn(false);
if (type == typeof(CheckState)) return new DataGridViewCheckBoxColumn(true);
if (typeof(Image).IsAssignableFrom(type)) return new DataGridViewImageColumn();
var imageConverter = TypeDescriptor.GetConverter(typeof(Image));
if (imageConverter.CanConvertFrom(type)) return new DataGridViewImageColumn();
if (!typeof(System.Collections.IList).IsAssignableFrom(type)) return new DataGridViewTextBoxColumn();
return null;
}
До сих пор так хорошо. К счастью, это не сложно. Во-первых, мы добавим еще одно создание типа столбца по умолчанию, основанное на типе свойства внутри указанного метода.Во-вторых, мы позволим вызывающему абоненту «переопределять» поведение по умолчанию для каждого свойства источника данных, тем самым позволяя создавать комбинированные поля и другие типы столбцов, которые нуждаются в дополнительной инициализации.
Для того, мы будем инкапсулировать его в методе пользовательских расширений со следующей подписью:
public static void Bind(
this DataGridView view,
object dataSource,
string dataMember = "",
Func<PropertyDescriptor, DataGridViewColumn> columnFactory = null)
dataSource
и dataMember
представляют соответствующие DataGridView
свойства, в то время как columnFactory
делегат точка расширения.
Вот полная реализация:
public static class DataGridViewExtensions
{
public static void Bind(this DataGridView view, object dataSource, string dataMember = "", Func<PropertyDescriptor, DataGridViewColumn> columnFactory = null)
{
var columns = new List<DataGridViewColumn>();
var properties = ListBindingHelper.GetListItemProperties(dataSource, dataMember, null);
for (int i = 0; i < properties.Count; i++)
{
var property = properties[i];
if (!property.IsBrowsable) continue;
var column = (columnFactory != null ? columnFactory(property) : null) ?? DefaultColumnFactory(property.PropertyType);
if (column == null) continue;
column.DataPropertyName = property.Name;
column.Name = property.Name;
column.HeaderText = !string.IsNullOrEmpty(property.DisplayName) ? property.DisplayName : property.Name;
column.ValueType = property.PropertyType;
column.ReadOnly = property.IsReadOnly;
columns.Add(column);
}
view.DataSource = null;
view.Columns.Clear();
view.AutoGenerateColumns = false;
view.Columns.AddRange(columns.ToArray());
view.DataMember = dataMember;
view.DataSource = dataSource;
}
private static DataGridViewColumn DefaultColumnFactory(Type type)
{
if (type == typeof(bool)) return new DataGridViewCheckBoxColumn(false);
if (type == typeof(CheckState)) return new DataGridViewCheckBoxColumn(true);
if (typeof(Image).IsAssignableFrom(type)) return new DataGridViewImageColumn();
var imageConverter = TypeDescriptor.GetConverter(typeof(Image));
if (imageConverter.CanConvertFrom(type)) return new DataGridViewImageColumn();
// Begin custom default factory
if (type == typeof(DateTime)) return new CalendarColumn();
// End custom default factory
if (!typeof(System.Collections.IList).IsAssignableFrom(type)) return new DataGridViewTextBoxColumn();
return null;
}
}
Примечание: CalendarColumn
используется из How to: Host Controls in Windows Forms DataGridView Cells MSDN например.
Описанный выше метод работает с DataTable
, DataSet
, а также каждого типа источника данных (IList
, IBindingList
, IListSource
и т.д.) при поддержке управления DataGridView
.
Использование с DataTable
просто как:
dataGridView.Bind(dataTable);
Демо::
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form();
var dg = new DataGridView { Dock = DockStyle.Fill, Parent = form };
dg.Bind(GetData());
Application.Run(form);
}
static DataTable GetData()
{
var dt = new DataTable();
dt.Columns.AddRange(new[]
{
new DataColumn("Id", typeof(int)),
new DataColumn("Name"),
new DataColumn("Description"),
new DataColumn("StartDate", typeof(DateTime)),
new DataColumn("EndDate", typeof(DateTime)),
});
dt.Rows.Add(1, "Foo", "Bar", DateTime.Today, DateTime.Today.AddDays(7));
return dt;
}
}
![enter image description here](https://i.stack.imgur.com/wygJ3.png)
* столбец 'DateTime' типа должен провести в' DateTimePicker' *, этот столбец является тем, который находится в вашем «DataTable» в настоящее время, или вы хотите создать новый столбец и добавить в свой «DataGridView» тогда запустите для него 'DateTimePicker'? –
У меня есть столбец типа DateTime, но я хочу вместо текущего TextBox отредактировать дату, показать 'DateTimePicker'. Я не знаю, как это сделать, поскольку значения не добавляются вручную, а rahter, используя код, который я показываю. Надеюсь, теперь это ясно. – Jack
Хорошо. Проверьте мой ответ, он основан на ссылке «MSDN», которую вы ищете. –