Связывание WPF DataGrid с DataTable с использованием TemplateColumns

Я пробовал все и никуда не уходил, поэтому я надеюсь, что кто-то сможет дать мне момент аха. Я просто не могу получить привязку, чтобы вытащить данные в datagrid.

У меня есть DataTable, который содержит несколько столбцов с MyDataType

public class MyData { string nameData {get;set;} bool showData {get;set;} } 

MyDataType имеет 2 свойства (строка, логическая) Я создал тест DataTable

 DataTable GetDummyData() { DataTable dt = new DataTable("Foo"); dt.Columns.Add(new DataColumn("AnotherColumn", typeof(MyData))); dt.Rows.Add(new MyData("Row1C1", true)); dt.Rows.Add(new MyData("Row2C1", false)); dt.AcceptChanges(); return dt; } 

У меня есть DataGrid WPF, который я хочу показать DataTable. Но все, что я хочу сделать, – это изменить способ отображения каждой ячейки для отображения [TextBlock] [Button] на ячейку со значениями, привязанными к объекту MyData, и это то, где я испытываю тонны проблем.

Мой XAML выглядит так

              

Теперь все, что я делаю после загрузки, – это попытаться связать DataTable с WPF DataGrid

 dt = GetDummyData(); dataGrid1.ItemsSource = dt.DefaultView; 

Появляются TextBlock и Button, но они не связываются, что оставляет их пустыми. Может ли кто-нибудь сообщить мне, если у них есть идея, как это исправить. Это должно быть простым, это то, что Microsoft заставляет нас поверить. Я установил Column.CellTemplate во время события AutoGenerating и не получил привязки.

Пожалуйста помоги!!!

    Изменить: обновлено, чтобы отразить вклад Арана Малхолленда (см. Комментарий)

    По-видимому, DataGrid передает всю DataRowView в каждую ячейку. Вот почему привязка не работает. Ваш DataTemplate ожидает, что DataContext будет иметь тип MyData , но вместо этого он имеет тип DataRowView . Мое предложенное (несколько хак-иш) обходное решение для получения DataContext вы хотите создать пользовательский DataGridTemplateColumn который будет извлекать необходимый элемент из DataRowView . Код ниже:

                    

     using System.Data; using System.Windows; using Microsoft.Windows.Controls; namespace DataGridTemplateColumnSample { public partial class Window1 { public Window1() { InitializeComponent(); DataContext = GetDummyData().DefaultView; } private static DataTable GetDummyData() { var dt = new DataTable("Foo"); dt.Columns.Add(new DataColumn("OneColumn", typeof(MyData))); dt.Columns.Add(new DataColumn("AnotherColumn", typeof(MyData))); dt.Rows.Add(new MyData("Row1C1", true), new MyData("Row1C2", true)); dt.Rows.Add(new MyData("Row2C1", false), new MyData("Row2C2", true)); dt.AcceptChanges(); return dt; } private void dataGrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { var column = new DataRowColumn(e.PropertyName); column.Header = e.Column.Header; column.CellTemplate = (DataTemplate)Resources["MyDataTemplate"]; e.Column = column; } } public class DataRowColumn : DataGridTemplateColumn { public DataRowColumn(string column) { ColumnName = column; } public string ColumnName { get; private set; } protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem) { var row = (DataRowView) dataItem; var item = row[ColumnName]; cell.DataContext = item; var element = base.GenerateElement(cell, item); return element; } } public class MyData { public MyData(string name, bool data) { nameData = name; showData = data; } public string nameData { get; set; } public bool showData { get; set; } } } 

    Примечание. Этот подход работает только с виртуализацией контейнера или в стандартном режиме. Если для параметра VirtualizationMode установлено значение Recycling, шаблон не применяется.

    После обнаружения этой темы и проблем с кодом, показанным здесь, я столкнулся с этим streamом в MSDN, и он работает намного лучше! Насколько я видел, проблем с виртуализацией вообще нет.

    http://social.msdn.microsoft.com/Forums/en/wpf/thread/8b2e94b7-3c44-4642-8acc-851de5285062

    Код:

     private void dataGrid1_AutoGeneratingColumn(object sender, Microsoft.Windows.Controls.DataGridAutoGeneratingColumnEventArgs e) { if (e.PropertyType == typeof(MyData)) { MyDataGridTemplateColumn col = new MyDataGridTemplateColumn(); col.ColumnName = e.PropertyName; // so it knows from which column to get MyData col.CellTemplate = (DataTemplate)FindResource("MyDataTemplate"); e.Column = col; e.Column.Header = e.PropertyName; } } public class MyDataGridTemplateColumn : DataGridTemplateColumn { public string ColumnName { get; set; } protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem) { // The DataGridTemplateColumn uses ContentPresenter with your DataTemplate. ContentPresenter cp = (ContentPresenter)base.GenerateElement(cell, dataItem); // Reset the Binding to the specific column. The default binding is to the DataRowView. BindingOperations.SetBinding(cp, ContentPresenter.ContentProperty, new Binding(this.ColumnName)); return cp; } } 
    Давайте будем гением компьютера.