How do I update an IValueConverter on CollectionChanged?

时光怂恿深爱的人放手 提交于 2019-11-29 14:40:17

I ended up doing something like this which seems to work. It's far from an optimal solution and I'd still be interested in something better but it seems to work for my purposes.

class CollectionChangedHandlingValueConverter : IValueConverter
{
    DependencyObject myTarget;
    DependencyProperty myTargetProperty;

    //If this ever needs to be called from XAML you can make it a MarkupExtension and use ProvideValue to set up the Target and TargetProperty
    public CollectionChangedHandlingValueConverter(DependencyObject target, DependencyProperty dp)
    {
        myTarget = target;
        myTargetProperty = dp;
    }

    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        INotifyCollectionChanged collection = value as INotifyCollectionChanged;
        if (collection != null)
        {
            //It notifies of collection changed, try again when it changes
            collection.CollectionChanged += DataCollectionChanged;
        }

        //Do whatever conversions here
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion

    void DataCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if ((myTarget != null) && (myTargetProperty != null))
        {
            BindingOperations.GetBindingExpressionBase(myTarget, myTargetProperty).UpdateTarget();
        }
    }
}

This is actually surprisingly very difficult. An IValueConverter doesn't update, so this does not work as you'd hope.

I wrote a sample on the Microsoft Expression Gallery called Collection Aggregator that shows a working, if convoluted, approach to making this work via a Behavior that does the aggregation (Count, in your case, although I also support Sum, Average, etc) for you, instead of a converter.

And I ended up synchronizing collection (original with converter), take a look at the buttom of my post for example:

http://alexburtsev.wordpress.com/2011/03/05/mvvm-pattern-in-silverlight-and-wpf/

In your model, subscribe to CollectionChanged and raise PropertyChanged:

Numbers.CollectionChanged += (o,e) => 
  OnPropertyChanged(new PropertyChangedEventArgs(nameof(Numbers)));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!