Search code examples
c#wpf.net-coredatatable

How to set a DataContext for DataTable.RowChanged Event code


I'm trying to run the code in DataTable.RowChanged Event, but I cannot set a DataContext and this gives me an error like this:

CS0120  An object reference is required
for the non-static field, method, or property 'FrameworkElement.DataContext'

Here is the code:

MainWindow.xaml.cs

using System;
using System.Data;
using System.Windows;

namespace DataTable_RowChanged
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataTableRowChanged();
        }

        private static void DataTableRowChanged()
        {
            DataTable custTable = new DataTable("Customers");
            // add columns
            custTable.Columns.Add("id", typeof(int));
            custTable.Columns.Add("name", typeof(string));
            custTable.Columns.Add("address", typeof(string));

            // set PrimaryKey
            custTable.Columns["id"].Unique = true;
            custTable.PrimaryKey = new DataColumn[] { custTable.Columns["id"] };

            // add a RowChanged event handler for the table.
            custTable.RowChanged += new DataRowChangeEventHandler(Row_Changed);

            // add ten rows
            //for (int id = 1; id <= 10; id++)
            for (int id = 0; id < 10; id++)
            {
                custTable.Rows.Add(
                    new object[] { id, string.Format("customer{0}", id),
            string.Format("address{0}", id) });
            }

            custTable.AcceptChanges();

            // change the name column in all the rows
            foreach (DataRow row in custTable.Rows)
            {
                row["name"] = string.Format("vip{0}", row["id"]);
            }

            // The line below causes the error:
            // CS0120   An object reference is required
            // for the non-static field, method, or property 'FrameworkElement.DataContext'
            DataContext = custTable; 
        }

        private static void Row_Changed(object sender, DataRowChangeEventArgs e)
        {
            Console.WriteLine("Row_Changed Event: name={0}; action={1}",
                e.Row["name"], e.Action);
        }
    }
}

MainWindow.xaml.cs

<Window x:Class="DataTable_RowChanged.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataTable_RowChanged"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid ItemsSource="{Binding}"/>
    </Grid>
</Window>

What I tried is to change this line:

for (int id = 1; id <= 10; id++)

to this line:

for (int id = 0; id < 10; id++)

... because I saw an extra null item after address. This didn't solve the problem.

I chose "WPF Application .NET Core 3.1" to create this project. Please tell me how to fix this. Thank you.


Solution

  • You need to cast sender to the FrameworkElement type.

        private static void Row_Changed(object sender, DataRowChangeEventArgs e)
        {
            Console.WriteLine("Row_Changed Event: name={0}; action={1}",
                e.Row["name"], e.Action);
            if(sender is FrameworkElement fe)
            {
                Console.WriteLine($"DataContext: {fe.DataContext}");
            }
        }
    

    I didn't understand in which method you want to get the DataContext of the row.
    Or do you need Window.DataContext?
    In this case, the DataTableRowChanged method must be an instance method.

        private /* static */ void DataTableRowChanged()
        {