Search code examples
c#wpfivalueconvertermultibinding

Converter not getting called at runtime


I have user control with dependency property selected items(which is a collection of enum values)

public IEnumerable SelectedItems
{
    get { return (IEnumerable)GetValue(SelectedItemsProperty); }
    set { SetValue(SelectedItemsProperty, value); }
}

public static readonly DependencyProperty SelectedItemsProperty =
    DependencyProperty.Register("SelectedItems", typeof(IEnumerable),
      typeof(UserControl1), new FrameworkPropertyMetadata(OnChangeSelectedItems)
      {
          BindsTwoWayByDefault = true
      });


private static void OnChangeSelectedItems(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var uc = d as UserControl1;

    if (uc != null)
    {
        var oldObservable = e.OldValue as INotifyCollectionChanged;
        var newObservable = e.NewValue as INotifyCollectionChanged;
        if (oldObservable != null)
        {
            oldObservable.CollectionChanged -= uc.SelectedItemsContentChanged;
        }
        if (newObservable != null)
        {
            newObservable.CollectionChanged += uc.SelectedItemsContentChanged;
            uc.UpdateMultiSelectControl();

        }
    }

}

private void SelectedItemsContentChanged(object d, NotifyCollectionChangedEventArgs e)
{
    UpdateMultiSelectControl();
}

I have binded selectedItems dependency property with a checkbox in my user control using a converter

<ItemsControl ItemsSource="{Binding Items}" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical">
                <CheckBox x:Name="ChkBox" Margin="13 0 0 10"  Content="{Binding}" >
                    <CheckBox.IsChecked>
                        <MultiBinding Converter="{StaticResource CheckBoxConverter}"  Mode="TwoWay" >
                            <Binding ElementName="ChkBox" Path="Content" />
                            <Binding  RelativeSource="{RelativeSource FindAncestor,AncestorType={x:Type UserControl}}"  Path="DataContext.SelectedItems" UpdateSourceTrigger="PropertyChanged"  Mode="TwoWay"></Binding>
                        </MultiBinding>
                    </CheckBox.IsChecked>

                </CheckBox>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl> 

and converter

public class CheckBoxConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType,
           object parameter, System.Globalization.CultureInfo culture)
    {
        if (values != null && values.Length > 1)
        {
            var content = values[0];
            var selected = values[1] as IList;

            if (selected != null && selected.Contains(content))
            {
                return true;
            }
        }

        return false;

    }
    public object[] ConvertBack(object value, Type[] targetTypes,
           object parameter, System.Globalization.CultureInfo culture)
    {
        return new[] { Binding.DoNothing, Binding.DoNothing };
    }
}

My problems is if I add values in Selected items at the time of construction the converter is getting called but if I add values on a button click ,its not getting called.Can anybody tell me the reason why its happening and how i can correct this one.


Solution

  • The Convert method of the converter only gets called when any of the properties that you bind to changes. You are binding to the Content property of the CheckBox and the SelectedItems property of the UserControl. Neither of these change when you add a new item to the collection.

    Try to also bind to the Count property of the collection:

    <CheckBox x:Name="ChkBox" Margin="13 0 0 10"  Content="{Binding}" >
        <CheckBox.IsChecked>
            <MultiBinding Converter="{StaticResource CheckBoxConverter}"  Mode="TwoWay" >
                <Binding ElementName="ChkBox" Path="Content" />
                <Binding RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}" Path="SelectedItems"/>
                <Binding RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}" Path="SelectedItems.Count"/>
            </MultiBinding>
        </CheckBox.IsChecked>
    </CheckBox>