Reputation: 3677
I have a ComboBox
that I need to do a converter on the SelectedItem
. Problem is the IValueConverter
needs the binding value but a Collection as well. Configured a DependencyObject
but it is giving me an error message of
Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.Collections.ObjectModel.ObservableCollection`1[MyClass]'.
Here is my IValueConverter
public class MyConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty FoldersProperty =
DependencyProperty.Register(nameof(MyCollection), typeof(ObservableCollection<MyClass>), typeof(MyClassModelToMyClassID), new FrameworkPropertyMetadata(new ObservableCollection<MyClass>()));
public ObservableCollection<MyClass> MyCollection
{
get { return GetValue(FoldersProperty) as ObservableCollection<MyClass>; }
set { SetValue(FoldersProperty, value); }
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//Amazing Convert code that uses MyCollection and Value
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
//Amazing ConvertBack code that uses MyCollection and Value
}
}
Here is how I am calling it:
<Page.Resources>
<converter:MyConverter x:Key="Converter" MyCollection="{Binding DataCollection}" />
</Page.Resources>
....
<ComboBox
ItemsSource="{Binding DataCollection}"
SelectedItem="{Binding Path=MyValue, Converter={StaticResource TaxCodeConverter}}" />
edit: added the full IValueConvert subtracted the Convert and ConvertBack code
Upvotes: 2
Views: 521
Reputation: 37060
Like a BindingProxy, it needs to be a Freezable. Also, don't pass a new observable collection to your metatadata. That's a reference type, so all instances of this converter will be initialized with the same actual collection instance.
Let me know if you run into some other issue, but I've done this and been able to bind to the dependency property.
Many would argue that a better approach would be a multibinding and a multi-value converter. I think there's value in having a strongly typed property with a descriptive name.
public class MyConverter : Freezable, IValueConverter
{
/* omitted: Convert() and ConvertBack() */
public MyConverter()
{
// Initialize here if you need to
MyCollection = new ObservableCollection<MyClass>();
}
protected override Freezable CreateInstanceCore()
{
return new MyConverter();
}
public static readonly DependencyProperty MyCollectionProperty =
DependencyProperty.Register(nameof(MyCollection),
typeof(ObservableCollection<MyClass>), typeof(MyConverter),
new FrameworkPropertyMetadata(null));
public ObservableCollection<MyClass> MyCollection
{
get { return GetValue(MyCollectionProperty) as ObservableCollection<MyClass>; }
set { SetValue(MyCollectionProperty, value); }
}
}
XAML usage will be just as you have it in your question: Bind the dependency property, and the binding will update that property of that instance of MyConverter
, provided that your Page's DataContext has an appropriately typed property named DataCollection
.
<Page.Resources>
<converter:MyConverter x:Key="Converter" MyCollection="{Binding DataCollection}" />
</Page.Resources>
Upvotes: 2