Como faço para atualizar um IVALUECONVERTER no ColecleThanged?
-
16-09-2019 - |
Pergunta
Aqui está um exemplo básico para explicar meu problema. Digamos que eu tenho
ObservableCollection<int> Numbers {get; set;}
e um IValueConverter que retorna a soma dos números.
Normalmente, o que eu faria é mudar o IVALUECONVERTER em um imultivalueConverter e vincular um segundo valor a números.
<MultiBinding Converter="{StaticResource SumTheIntegersConverter}">
<Binding Path="Numbers" />
<Binding Path="Numbers.Count" />
</MultiBinding>
No entanto, não consigo usar esse método para resolver meu problema real. Parece que deve haver uma maneira melhor de atualizar a ligação quando a coleção muda em que eu simplesmente não estou pensando. Qual é a melhor maneira de executar o conversor de valor quando os itens são adicionados e removidos aos números?
Solução
Acabei fazendo algo assim que parece funcionar. Está longe de ser uma solução ideal e eu ainda estaria interessado em algo melhor, mas parece funcionar para meus propósitos.
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();
}
}
}
Outras dicas
Isso é realmente surpreendentemente muito difícil. Um IVALUECONVERTER não atualiza, então isso não funciona como você espera.
Eu escrevi uma amostra na galeria da Microsoft Expression chamada Agregador de coleções Isso mostra uma abordagem de funcionamento, se complicada, para fazer esse trabalho através de um comportamento que faz a agregação (contagem, no seu caso, embora eu também apóie a soma, a média etc.) para você, em vez de um conversor.
E acabei sincronizando a coleção (original com conversor), dê uma olhada no Buttom da minha postagem, por exemplo:
http://alexburtsev.wordpress.com/2011/03/05/mvvm-pattern-in-silverlight-and-wpf/
Em seu modelo, inscreva -se na Coleção e levante a PropertyChanged:
Numbers.CollectionChanged += (o,e) =>
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Numbers)));