Raj
Raj

Reputation: 33

Update all parents when shared nested object gets updated

I have below class hierarchy.

public class RowViewModel : BaseViewModel
    {
        private CellViewModel cell;
        public CellViewModel Cell
        {
            get { return cell; }
            set
            {
                cell = value;
                OnPropertyChanged("Cell");
            }
        }
    }

public class CellViewModel : BaseViewModel
    {
        public string Text { get { return string.Join("\n", CellLinks.Select(c => c.Text)); } }
        private ObservableCollection<CellLinkViewModel> cellLinks;
        public ObservableCollection<CellLinkViewModel> CellLinks
        {
            get
            { return cellLinks; }
            set
            {
                cellLinks = value;
                OnPropertyChanged("CellLinks");
            }
        }
    }
public class CellLinkViewModel : BaseViewModel
    {
        public string Text
        {
            get { return CellValue.Text; }
            set
            {
                CellValue.Text = value;
                OnPropertyChanged("Text");              
            }
        }
        public CellValueViewModel CellValue { get; set; }
    }
public class CellValueViewModel : BaseViewModel
    {
        public string Text { get; set; }
    }
public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
                PropertyChanged(this, e);
            }
        }
    }

XAML code looks like,

<DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="#" Width="200">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Cell.Text}"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ListBox ItemsSource="{Binding Cell.CellLinks}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding Text, Mode=TwoWay}"/>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

CellValueViewModel is shared across multiple CellLinkViewModel. When I change CellValueViewModel it should have propagated changes to all dependent parents and DataGrid should show all latest values.

This is result

This is result

But I think its not happening automatically, am I missing something here? How to notify all datagrid cells to update automatically when the nested objects gets updated.

Upvotes: 2

Views: 60

Answers (1)

mm8
mm8

Reputation: 169420

You need to hook up event handlers to the PropertyChanged event for all CellLinkViewModel objects and raise the PropertyChanged event for the Text property of the CellViewModel whenever a link is modified, e.g.:

public class CellViewModel : BaseViewModel
{
    public string Text { get { return string.Join("\n", CellLinks.Select(c => c.Text)); } }

    private ObservableCollection<CellLinkViewModel> cellLinks;
    public ObservableCollection<CellLinkViewModel> CellLinks
    {
        get
        {
            return cellLinks;
        }
        set
        {
            cellLinks = value;
            if(cellLinks != null)
            {
                foreach(var link in cellLinks)
                {
                    link.PropertyChanged += Link_PropertyChanged;
                }
            }
            OnPropertyChanged("CellLinks");
        }
    }

    private void Link_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        OnPropertyChanged("Text");
    }
}

You probably also want to handle the CollectionChanged event for the ObservableCollection<CellLinkViewModel> and hook up event handlers to dynamically added CellLinkViewModel objects as well.

Upvotes: 1

Related Questions