Home > Blockchain >  Why do I have to use type casting between objects with Content properties using a DataGrid in WPF?
Why do I have to use type casting between objects with Content properties using a DataGrid in WPF?

Time:11-24

I created a WPF project using Entity Framework and MSSQL.

The problem is when I want to display the content of id I have to typecast it to TextBlock because otherwise, I get an error message and I don't know what is the reason, why I have to do this.

This is the line that I am talking about: lblID.Content = ((TextBlock)id.Content).Text;

Why can't I just write:lblID.Content = id.Content; With this code when I load the DataGrid and select a row, the id value from the first column disappears and when the last one disappears too, a NullReferenceException will pop up: The value of the id disappears

Here is my whole code:

    public partial class MainWindow : Window
    {
        hospitalEntities hp = new hospitalEntities();
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeTable();
        }

        private void InitializeTable()
        {
            dgPatientTable.ItemsSource = null;
            var query = from patient in hp.patients
                        select
                        new
                        {
                            patient.ID,
                            patient.name,
                            patient.phone,
                            patient.email,
                            patient.address,
                            patient.postalZip
                        };
            dgPatientTable.ItemsSource = query.ToList();
        }

        private void btnAddPatient_Click(object sender, RoutedEventArgs e)
        {
            using (hp)
            {
                patient Patient = new patient()
                {
                    name = tbName.Text,
                    phone = tbPhone.Text,
                    email = tbEmail.Text,
                    address = tbAddress.Text,
                    postalZip = tbPostalZip.Text
                };
                hp.patients.Add(Patient);
                hp.SaveChanges();
                tbName.Text = "";
                tbPhone.Text = "";
                tbEmail.Text = "";
                tbAddress.Text = "";
                tbPostalZip.Text = "";
                InitializeTable();
            }
        }

        int patientId = 0;
        private void dgPatientTable_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dataGrid = sender as DataGrid;
            DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator
                                .ContainerFromIndex(dataGrid.SelectedIndex);
            DataGridCell id;
            try
            {
                id = (DataGridCell)dataGrid.Columns[0].GetCellContent(row).Parent;
            }
            catch
            {
                return;
            }

            lblID.Content = ((TextBlock)id.Content).Text;

            try
            {
                patientId = int.Parse(((TextBlock)id.Content).Text);
            }
            catch
            {
                patientId = 0;
                return;
            }
            DataGridCell name = (DataGridCell)dataGrid.Columns[1].GetCellContent(row).Parent;
            tbNameUpdate.Text = ((TextBlock)name.Content).Text;
            DataGridCell phone = (DataGridCell)dataGrid.Columns[2].GetCellContent(row).Parent;
            tbPhoneUpdate.Text = ((TextBlock)phone.Content).Text;
            DataGridCell email = (DataGridCell)dataGrid.Columns[3].GetCellContent(row).Parent;
            tbEmailUpdate.Text = ((TextBlock)email.Content).Text;
            DataGridCell address = (DataGridCell)dataGrid.Columns[4].GetCellContent(row).Parent;
            tbAddressUpdate.Text = ((TextBlock)address.Content).Text;
            DataGridCell postalZip = (DataGridCell)dataGrid.Columns[5].GetCellContent(row).Parent;
            tbPostalzipUpdate.Text = ((TextBlock)postalZip.Content).Text;
        }
    }

CodePudding user response:

Because you're working with Visual elements, not the data they represent.

I don't have a complete understanding of the data types and architecture you are using. Therefore, my example is not the exact implementation, but showing the path to it.

    public partial class MainWindow : Window
    {
        hospitalEntities hp = new hospitalEntities();
        private readonly ObservableCollection<PatientEntity> patients = new(); 
        public MainWindow()
        {
            InitializeComponent();

            // Setting once after initialization XAML.
            dgPatientTable.ItemsSource = patients;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeTable();
        }

        private void InitializeTable()
        {
            patients.Clear();
            hp.patients.ToList().ForEach(p => patients.Add(p));
        }


        int patientId = 0;
        private void dgPatientTable_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dataGrid = sender as DataGrid;
            if(dataGrid.SelectedItem is PatientEntity patient)
            {
                // Some code that works with the selected patient.
            }
        }

You also work incorrectly with the Add and Update regions. But for the purpose of showing an example, the XAML of your layout matters.
Please post it in your question.

I can't find the logic behind this line: lblID.Content = id.Content; and I just want to understand why it is not working. What is the reason?

Because from the ItemContainerGenerator you get not data (patient), but UI elements representing them. To get the data, you just need to extract it from dataGrid.SelectedItem and cast it to its original type. But you can't do it. Because your query returns you a list with an anonymous class. And you cannot cast SelectedItem to an anonymous class.

Therefore, you first need to create a collection for the source DataGrid.This collection must be of a named type so that you can cast SelectedItem to that type.

  • Related