1

I have a strange bug with my DataTemplate "PersonDataTemplate" I use it as CellTemplate and asCellEditingTemplate. On my CellTemplate all works fine but on my CellEditingTemplate I get following Error

System.Windows.Data Error: 40 : BindingExpression path error: 'PersonId' property not found on 'object' ''DataRowView' (HashCode=59318978)'. BindingExpression:Path=PersonId; DataItem='DataRowView' (HashCode=59318978); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'PersonName' property not found on 'object' ''DataRowView' (HashCode=59318978)'. BindingExpression:Path=PersonName; DataItem='DataRowView' (HashCode=59318978); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

My Template

    <DataTemplate x:Key="PersonDataTemplate" DataType="Person">
        <StackPanel>
            <TextBlock Background="LightBlue" Text="{Binding PersonId}"/>
            <TextBlock Background="AliceBlue" Text="{Binding PersonName}"/>
        </StackPanel>
    </DataTemplate>

and here is the rest of my Code

Person.cs

 public class Person
    {
        private int personId;
        private string personName;

        public int PersonId
        {
            get { return personId; }
            set { personId = value; }
        }
        public string PersonName
        {
            get { return personName; }
            set { personName = value; }
        }
    }

MainWindow.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        simpleDataGrid.ItemsSource = LoadDataTable().AsDataView();
    }

    /// <summary>
    /// Here i place my PersonDataTemplate as CellTemplate and CellEditingTemplate
    /// </summary>
    private void simpleDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (e.PropertyType == typeof(Person))
        {
            MyDataGridTemplateColumn col = new MyDataGridTemplateColumn();
            col.ColumnName = e.PropertyName;
            col.CellTemplate = (DataTemplate)FindResource("PersonDataTemplate");
            col.CellEditingTemplate = (DataTemplate)FindResource("PersonDataTemplate");
            e.Column = col;
            e.Column.Header = e.PropertyName;
        }
    }

    /// <summary>
    /// Here I create and fill my DataTable
    /// </summary>
    private DataTable LoadDataTable()
    {
        var _simpleDataTable = new DataTable();

        var person = new DataColumn("Person") { DataType = typeof(Person) };
        _simpleDataTable.Columns.Add(person);

        var dr1 = _simpleDataTable.NewRow();
        dr1[0] = new Person { PersonId = 1, PersonName = "TONY" };
        _simpleDataTable.Rows.Add(dr1);

        var dr2 = _simpleDataTable.NewRow();
        dr2[0] = new Person { PersonId = 2, PersonName = "MAL" };
        _simpleDataTable.Rows.Add(dr2);

        _simpleDataTable.AcceptChanges();

        return _simpleDataTable;
    }

    private void simpleDataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
    {
        // just to check the Values
    }
}

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;
    }
}

MainWindow.XAML

<Window x:Class="HowBindDataTableToDataGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <!-- you for each Class one DataTemplate-->
        <DataTemplate x:Key="PersonDataTemplate" DataType="Person">
            <StackPanel>
                <TextBlock Background="LightBlue" Text="{Binding PersonId}"/>
                <TextBlock Background="AliceBlue" Text="{Binding PersonName}"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <DataGrid Name="simpleDataGrid" AutoGeneratingColumn="simpleDataGrid_AutoGeneratingColumn" BeginningEdit="simpleDataGrid_BeginningEdit" />
    </Grid>
</Window>

Special Information's

  • My ItemsSource is a DataTable
  • My MyDataGridTemplateColumn based on this Answer (I also tested the other solution with no luck)
  • I also tested a separate DataTemplate for my CellEditingTemplate with no luck
Community
  • 1
  • 1
WiiMaxx
  • 5,322
  • 8
  • 51
  • 89

1 Answers1

1

You should override GenerateEditingElement too, then set the content of the generated element like you did on GenerateElement method :

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;
    }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        // The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
        ContentPresenter cp = (ContentPresenter)base.GenerateEditingElement(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;
    }

}
Karl_Schuhmann
  • 1,272
  • 5
  • 17
  • 37
user1064519
  • 2,180
  • 12
  • 13