2016-05-27 6 views
3

У меня есть DataGridView, который я заселить данные автоматически, в соответствии со следующим:Хост пользовательских элементов управления на DataGridView, которые населяют данные из DataTable

MySqlDataAdapter adapter = new MySqlDataAdapter(query, connString); 
DataTable table = new DataTable(); 
table.Locale = System.Globalization.CultureInfo.InvariantCulture; 
adapter.Fill(table); 
e.Result = table; 

Так нет явных dataGridView1.Columns.Add() вызовов на всех.

Я хочу сделать столбцы определенного типа хостом определенного элемента управления, например, столбец DateTime должен содержать DateTimePicker. Воображаемый пример кода:

private void dataGridView1_ColumnCreating(object sender, DataGridViewColumnEventArgs e) 
{ 
    if(e.Column.ValueType is DateTime) 
    { 
     e.Column = new MyCalendarColumn(); 
    } 
} 

Или создать класс, который наследует от DataGridView и добавить свою собственную поддержку типа столбца.

Как я могу это сделать? Я искал событие, выпущенное во время создания столбца, или как добавить свой собственный тип столбца, наследуя от DataGridView или около того. Но я мог найти только примеры, когда столбцы добавляются вручную, а не заполняя дату, используя DataTable.

+0

* столбец 'DateTime' типа должен провести в' DateTimePicker' *, этот столбец является тем, который находится в вашем «DataTable» в настоящее время, или вы хотите создать новый столбец и добавить в свой «DataGridView» тогда запустите для него 'DateTimePicker'? –

+0

У меня есть столбец типа DateTime, но я хочу вместо текущего TextBox отредактировать дату, показать 'DateTimePicker'. Я не знаю, как это сделать, поскольку значения не добавляются вручную, а rahter, используя код, который я показываю. Надеюсь, теперь это ясно. – Jack

+0

Хорошо. Проверьте мой ответ, он основан на ссылке «MSDN», которую вы ищете. –

ответ

2

Если вы ищете нативный подход, предложенный MSDN here, в первую очередь вы должны установить AutoGenerateColumns свойства вашего DataGridView в false:

dataGridView1.AutoGenerateColumns = false; 

Затем вам нужно добавить столбцы, которые вы хотите появляются в DataGridView вот так. (Обратите внимание, что Id и Name и BirthDate являются вымышленными именами столбцов в таблице, поэтому изменить их в свои фактические имена столбцов):

SMySqlDataAdapter adapter = new MySqlDataAdapter(query, connString); 
DataTable table = new DataTable(); 
table.Locale = System.Globalization.CultureInfo.InvariantCulture; 
adapter.Fill(table); 
e.Result = table; 
dataGridView1.AutoGenerateColumns = false; 
dataGridView1.DataSource = table; 

DataGridViewColumn(table.Columns[0].ColumnName, new DataGridViewTextBoxColumn()); 
DataGridViewColumn(table.Columns[1].ColumnName, new DataGridViewTextBoxColumn()); 
DataGridViewColumn(table.Columns[2].ColumnName, new DataGridViewTextBoxColumn()); 
DataGridViewColumn(table.Columns[3].ColumnName, new CalendarColumn());//Create the CalendarColumn class as MSDN suggested 


private void DataGridViewColumn(string colName, DataGridViewColumn colType) 
{ 
    colType.DataPropertyName = colName; 
    colType.HeaderText = colName; 
    colType.Name = colName; 
    dataGridView1.Columns.Add(colType); 
} 

Пожалуйста, обратите внимание, что CalendarColumn это класс, который находится в ссылке MSDN ,

+0

Удивительно! Большое вам спасибо, наконец, мне это удалось. Полностью стоит дать это 50 – Jack

+0

@Jack ... You're Welcome . Удачи. :) –

0

Попробуйте событие ColumnAdded, есть взгляд на следующее определение:

public event DataGridViewColumnEventHandler ColumnAdded 

Это событие происходит, когда столбец добавляется к элементу управления DataGridView.

Вот пример:

private void DataGridView1_ColumnAdded(Object sender, DataGridViewColumnEventArgs e) { 

if(e.Column.ValueType is DateTime) { 
      e.Column = new MyCalendarColumn(); 
     } 
} 

Позвольте мне знать, если это помогает.

+0

'e.Column' is readonly – Jack

+0

Вы пытались изменить это состояние? GridView1.columns [1] .ReadOnly = false; – Sizons

+0

Вот еще один пример:! защищен недействительным GridView1_RowCreated (объект отправителя, GridViewRowEventArgs е) { Еогеасп (TableCell клеток в e.Row.Cells) { если (string.IsNullOrEmpty (cell.Text) && cell.Text = "   ") { Поле BoundField = (BoundField) ((DataControlFieldCell))) .СодержаниеField; if (поле.DataField == "ID") field.ReadOnly = true; } } } – Sizons

1

Как я понимаю вопрос, у вас есть 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