I have an ObservableCollection bound to a list box and a boolean property bound to a button. I then defined two converters, one that operates on the collection and the other operates on the boolean property. Whenever I modify the boolean property, the converter's Convert method is called, where as the same is not called if I modify the observable collection. What am I missing??
Snippets for your reference,
xaml snipet,
<Window.Resources>
<local:WrapPanelWidthConverter x:Key="WrapPanelWidthConverter" />
<local:StateToColorConverter x:Key="StateToColorConverter" />
</Window.Resources>
<StackPanel>
<ListBox x:Name="NamesListBox" ItemsSource="{Binding Path=Names}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel x:Name="ItemWrapPanel" Width="500" Background="Gray">
<WrapPanel.RenderTransform>
<TranslateTransform x:Name="WrapPanelTranslatation" X="0" />
</WrapPanel.RenderTransform>
<WrapPanel.Triggers>
<EventTrigger RoutedEvent="WrapPanel.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="WrapPanelTranslatation" Storyboard.TargetProperty="X" To="{Binding Path=Names,Converter={StaticResource WrapPanelWidthConverter}}" From="525" Duration="0:0:2" RepeatBehavior="100" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</WrapPanel.Triggers>
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Label Content="{Binding}" Width="50" Background="LightGray" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="{Binding Path=State}" Background="{Binding Path=State, Converter={StaticResource StateToColorConverter}}" Width="100" Height="100" Click="Button_Click" />
</StackPanel>
code behind snippet
public class WrapPanelWidthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<string> aNames = value as ObservableCollection<string>;
return -(aNames.Count * 50);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class StateToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool aState = (bool)value;
if (aState)
return Brushes.Green;
else
return Brushes.Red;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think the converter in a Binding
is always called if the Binding
source has been updated and notifies about that update (as a DependencyProperty
or using INotifyPropertyChanged
). However, an ObservableCollection
does not raise the PropertyChanged
event if an item has been added or removed, but it raises the CollectionChanged
event. It does not raise any event at all if an item in the collection is changed. Even if the item itself raises PropertyChanged
, this will not update the Binding
on the collection since the Binding
source is not the item, but the collection.
I fear your approach will not work this way. You could bind directly to ObservableCollection.Count
and add an appropriate math converter to it to perform the inversion and multiplication, but the Count
property does not perform change notification, so this no option. I think you will have to provide another property in your ViewModel or code-behind which handles these cases...