why the converter is not running?

64 views Asked by At

I am using the MVVM pattern and in my view I have this dataGrid:

<Setter Property="Background">
    <Setter.Value>
        <MultiBinding Converter="{StaticResource myMultiValueConverter}">
            <MultiBinding.Bindings>
                <Binding />
                <Binding ElementName="ThisControl" Path="DataContext.MyObservableCollectionInViewModel"/>
                <Binding ElementName="thisControl" Path="DataContext.ControlType"/>
                <Binding ElementName="ThisControl" Path="DataContext.ExternalItems"/>
                <Binding Path="Componentes.OneProperty"/>
            </MultiBinding.Bindings>
        </MultiBinding>
    </Setter.Value>
</Setter>

And my view model has this code:

private void myMethod()
{
    MyObservableCollectionInViewModel.Clear();
    MyObservableCollectionViewModel.Add(new myType());
}

When I execute the method MyMethod(), if a I am not wrong, the multi value converter would be run, because the ObservableCollection implements INotifyPropertyChanged when I add or remove items, but in this case does not work.

However I have another ObservableCollection for the DataSource of my dataGrid and it works as it's expected, refresh the dataGrid when I add or remove items from the ObservableCollection.

However, if in myMethod I do this:

private myMethod()
{
    myObservableCollectionInMyViewModel.Clear();
    myObservableCollectionInMyViewModel.Add(new MyType());
    myObservableCollectionInMyViewModel = new ObservableCollection(myObservableCollectionInMyViewModel);
}

It works, so the view is notified when I create a new ObservableCollection, not when I add or remove items from the actual ObservableCollecion.

1

There are 1 answers

0
Erti-Chris Eelmaa On BEST ANSWER

Yes, that's the correct behavior.

The reason the ObservableCollection Add/Remove works for ItemsControl, ListBox, DataGrid etc, is that they are explictly taking care of the behavior you are describing, that is not WPF specific, eg: it doesn't have to do with the actual binding of ItemsSource.

What happens under the cover is, all these controls(ListBox, etc..) are inheriting from ItemsControl which ultimately wraps ItemsSource into CollectionView, which will take advantange of INotifyCollectionChanged interface, if possible. That's how it knows / keeps up.

The "work-around" I've used successfully:

A) Just use property changed or do the swap as you've done (this might, or might not work - I don't exactly remember, but WPF might have explicit check if the actual value has been changed, in this case: it hasn't):

 myObservableCollectionInMyViewModel.Clear();
 myObservableCollectionInMyViewModel.Add(new MyType());
 RaisePropertyChanged(() => myObservableCollectionInMyViewModel);

B)

myObservableCollectionInMyViewModel = 
   new ObservableCollection(new List<MyType>{
      new MyType()});

C) Bind against .Count, as ObservableCollection will notify when that changes.

     <Binding ElementName="ThisControl" 
Path="DataContext.MyObservableCollectionInViewModel.Count"/

D) Create a new converter which will be able to listen all the events(INotifyPropertyChanged and INotifyCollectionChanged) events, which then will trigger multi converter updates.

<Binding ElementName="ThisControl" 
   Converter="{StaticResource observableConverter}"
   Path="DataContext.MyObservableCollectionInViewModel"/>