Errors Changed inside Collection Changed event does not get raised

181 Views Asked by At

I have an fullproperty like that in my VM:

public ObservableCollection<ServiceHost> ServiceHosts
{
    get => serviceHosts;
    set
    {
        if (serviceHosts == value) { return; }
        serviceHosts = value;
        OnPropertyChanged();
    }
}

In my other ViewModel for my MainWindow I'm using the CollectionChanged event on the ServiceHosts property to get the item that was added, convert it to my expected Type and listen to ErrorsChanged event that is a property from that type.
This looks like that:

ServiceHostViewModel.ServiceHosts.CollectionChanged += ServiceHostsOnCollectionChanged;

private void ServiceHostsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        if (e.NewItems[0] is ServiceHost newItems)
        {
            newItems.Validator = new ServiceHostValidator();
            newItems.ErrorsChanged += (o, args) => UpdateAllErrors();
            newServiceHost.ValidateAllProperties();

        }
    }
}

Unfortunately the ErrorsChanged event never triggers the UpdateAllErrors method, even when the cells show a red border, this event doesn't execute and I don't know why.
Here is a working example where I also use the ErrorsChanged event, but here I add the data to ServiceHosts from code and not the UI:

private void SetErrorsChangedEventToAllServiceHosts(XmlParserBase xmlParserBase)
{
    foreach (var serviceHost in xmlParserBase.GetServiceHostClients(new ServiceHostValidator()))
    {
        ServiceHostViewModel.ServiceHosts.Add(serviceHost);
        serviceHost.ErrorsChanged += (sender, args) => UpdateAllErrors();
    }
}

Why does the ErrorsChanged event in the ServiceHostsOnCollectionChanged doesn't work?
Any help is appreciate.

Update by comment: Here is some code from my model class

public class ServiceHost : INotifyDataErrorInfo
{
    public IValidator<ServiceHost> Validator;

    public ServiceHost(IValidator<ServiceHost> validator)
    {
        this.Validator = validator;
        this.Validator.ErrorsChanged += (s, e) => OnErrorsChanged(e);
    }
}
2

There are 2 best solutions below

0
Stan1k On BEST ANSWER

I just found a working solution. Like I mentioned in the comments to @mm8 I found out that this code:

Validator.ErrorsChanged += (s, e) => OnErrorsChanged(e);

which was in my constructor, never got called because by using e.NewItems[0] is ServiceHost newServiceHost to check my runtime type I didn't create a new instance and therefore didn't called the constructor. I tried moving that part outside the constructor and inside ValidateAllProperties method which works fine now.

In my case this method gets called immediately after I'm subscribing to ErrorsChanged property from MainWindow VM.

newServiceHost.ErrorsChanged += (o, args) => UpdateAllErrors();

If you have assumptions or better ideas let me know.

6
mm8 On

Unfortunately the ErrorsChanged event never triggers the UpdateAllErrors method, even when the cells show a red border, this event doesn't execute and I don't know why.

It's up to the class that implements the INotifyDataErrorInfo interface to explicitly raise the ErrorsChanged event

It doesn't get raised by the framework whenever the cells show a red border. The red border could for example mean that the source property could not even be set. For example, you cannot set a property of a type T to any other value than an instance of T.