DataGrid CellEditingTemplate上的BindingError 40

时间:2013-05-06 07:22:28

标签: c# wpf binding datagrid

我的DataTemplatePersonDataTemplate”我有一个奇怪的错误,我将其用作CellTemplateCellEditingTemplate。在我的CellTemplate上,一切正常,但在CellEditingTemplate上,我收到了错误

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')

我的模板

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

这是我的代码的其余部分

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>

特殊信息

  • 我的ItemsSource是一个DataTable
  • 我的MyDataGridTemplateColumn基于this答案(我也测试了其他解决方案但没有运气)
  • 我还为我的CellEditingTemplate测试了一个单独的DataTemplate而没有运气

1 个答案:

答案 0 :(得分:1)

你也应该覆盖GenerateEditingElement,然后像在GenerateElement方法上那样设置生成元素的内容:

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

}