Search code examples
wpfwpfdatagrid

WPF DataGrid cell bound to Property of Property in domain object not updating


I've tried to get at this problem from a few angles. Here I've tried to simplify it into a small test case.

I'm having problems getting a DataGrid cell to update which is bound to a property of a property. The property is set by a bound ComboBox cell in another column. The bound object is a follows, with the property I'm referring to:

public class MainObject : INotifyPropertyChanged
{
  private int _subObjectId;
  public virtual SubObject SubObjectObj { get; set; }
  public int SubObjectId { 
      get { return _subObjectId; }
      set { _subObjectId = value; SubObjectObj = <GetObjFromDB> }; 
  }
  ...
}

public class SubObject : INotifyPropertyChanged
{ 
  public int Id { get; set; }
  public string Name { get; set; }
  public string Specialty{ get; set; }
  ...
}

The DataGrid ItemsSource is

public ObservableCollection<MainObject> SourceData;

Now, the column in the DataGrid is a ComboBox of SubObject choices. A TextBox column next to it which is (supposed) to display the SubObject.Specialty of whatever SubObject is selected in the ComboBox.

      <DataGridTemplateColumn Header="SubObjects">

        <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
            <TextBlock Text="{Binding SubObject.Name, UpdateSourceTrigger=PropertyChanged}"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>

        <DataGridTemplateColumn.CellEditingTemplate>
          <DataTemplate>
            <ComboBox x:Name="ComboBoxSubObject" ItemsSource="{Binding Model.SubObjects, RelativeSource={RelativeSource AncestorType={x:Type uch:TestControl}}}" 
                      DisplayMemberPath="Name" 
                      SelectedValuePath="Id"
                      SelectedValue="{Binding SubObjectId, UpdateSourceTrigger=PropertyChanged}" 
                      SelectionChanged="ComboBoxDoctor_OnSelectionChanged"/>
          </DataTemplate>
        </DataGridTemplateColumn.CellEditingTemplate>

      </DataGridTemplateColumn>

      <DataGridTextColumn Header="Specialty" Binding="{Binding Path=SubObjectObj.Specialty}"/>          

When the grid is initially painted, the Specialty column is correct - it's the property is what SubObject is displayed in the other column. But when I change the ComboBox, the Specialty column does not change. Is there anyway to tell the DataGrid that the Specialty column binding source has changed and to refresh?

Thanks for any advice.


Solution

  • Is there anyway to tell the DataGrid that the Specialty column binding source has changed and to refresh?

    Yes, this is where your INotifyPropertyChanged implementation comes into play. You should have an OnPropertyChanged event as part of that implementation, invoking this event with a property name tells WPF that the property value has changed and to update the UI. You should call OnPropertyChanged for the Speciality property when your SubObject changes. Because they're in different classes, you'll probably need to expose a method or an event to do this:

    public class SubObject : INotifyPropertyChanged
    { 
        public int Id { get; set; }
        public string Name { get; set; }
        public string Specialty{ get; set; }
    
    
        public void OnSpecialityChanged()
        {
            OnPropertyChanged("Speciality");
        }
    }
    
    public class MainObject : INotifyPropertyChanged
    {
        private int _subObjectId;
        public virtual SubObject SubObjectObj { get; set; }
        public int SubObjectId 
        { 
            get { return _subObjectId; }
            set 
            { 
                _subObjectId = value; 
                SubObjectObj = <GetObjFromDB>
                SubObjectObj.OnSpecialityChanged();
            } 
        }
    }
    

    Side point, I'm unsure of what use your SubObjectId property is serving here. Could you instead maybe use the Id property directly from the SubObjectObj?