1
votes

I created a small sample-application in WPF to demonstrate my current issue: In my application I have two DataGrids.

  • The first DataGrid is bound to an ObservableCollection of my own Person-Objects and it just shows one property of every Person-Object.
  • In the second DataGrid I want to show all Person-Details based on the selected item in my first DataGrid.

Unfortunately my second DataGrid does not upate resp. show anything when I select an item in the first DataGrid and although I googled and read a lot of stuff, I'm not able to solve it myself.

So this is what I got in my DGUpdate-Application:

The MainWindow with both DataGrids, the DataContext etc.:

<Window x:Class="DGUpdate.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:DGUpdate"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindow_ViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <DataGrid
            Grid.Column="0"
            ItemsSource="{Binding MyObeservableCollectionOfPerson}" 
            SelectedItem="{Binding Path=SelectedPerson, Mode=TwoWay}"
            AutoGenerateColumns="False"
            IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Last name" Width="Auto" Binding="{Binding LastName}"/>
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid
            Grid.Column="1"
            ItemsSource="{Binding SelectedPerson}" 
            AutoGenerateColumns="False"
            IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Last name" Width="Auto" Binding="{Binding SelectedPerson.LastName}"/>
                <DataGridTextColumn Header="First name" Width="Auto" Binding="{Binding SelectedPerson.FirstName}"/>
                <DataGridTextColumn Header="Age" Width="Auto" Binding="{Binding SelectedPerson.Age}"/>
                <DataGridTextColumn Header="Weight" Width="Auto" Binding="{Binding SelectedPerson.Weight}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

My ViewModel that also implements INotifyPropertyChanged and where I create two demo-Persons in the Constructor:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace DGUpdate
{
    public class MainWindow_ViewModel : INotifyPropertyChanged
    {
        #region Properties
        public ObservableCollection<Person_Model> MyObeservableCollectionOfPerson { get; set; }
        public Person_Model SelectedPerson { get; set; }
        #endregion

        #region Constructor
        public MainWindow_ViewModel()
        {
            MyObeservableCollectionOfPerson = new ObservableCollection<Person_Model>();

            MyObeservableCollectionOfPerson.Add(
                new Person_Model()
                {
                    LastName = "Doe",
                    FirstName = "John",
                    Age = 32,
                    Weight = 90.3
                });
            MyObeservableCollectionOfPerson.Add(
                new Person_Model()
                {
                    LastName = "Miller",
                    FirstName = "Peter",
                    Age = 41,
                    Weight = 75.7
                });
        }
        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}

My own Person-Class with the four Properties that I want to be displayed in the second DataGrid based on the Person I selected in my first DataGrid:

namespace DGUpdate
{
    public class Person_Model
    {
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public int Age { get; set; }
        public double Weight { get; set; }
    }
}

As you can see, in my ViewModel-Class, I created a Person-Object 'SelectedPerson' that is bound to the SelectedItem of my first DataGrid and that I use as the ItemSource of my second DataGrid. I also played around a bit with manually calling the NotifyPropertyChanged, but this unfortunately also did not work and thus I removed it from this Sample-Application.

Can someone give me advice on how to solve the above described issue?

1

1 Answers

1
votes

You must call NotifyPropertyChanged() in your property like this :

private Person_Model selectedPerson;

public Person_Model SelectedPerson { 
  get
  {
    return this.selectedPerson;
  }

  set
  {
    if (value != this.selectedPerson)
    {
      this.selectedPerson = value;
      NotifyPropertyChanged();
    }
  }
}

More details on the doc: https://docs.microsoft.com/fr-fr/dotnet/framework/winforms/how-to-implement-the-inotifypropertychanged-interface