IValueConverter и привязка объекта DependencyObject - PullRequest
1 голос
/ 21 октября 2019

У меня есть ComboBox, что мне нужно сделать конвертер на SelectedItem. Проблема в том, что IValueConverter требуется значение привязки, но также и коллекция. Настроил DependencyObject, но выдает сообщение об ошибке

Объект типа 'System.Windows.Data.Binding' не может быть преобразован в тип 'System.Collections.ObjectModel.ObservableCollection`1. [MyClass] '.

Вот мой 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
    }
}

Вот как я его называю:

<Page.Resources>
    <converter:MyConverter x:Key="Converter" MyCollection="{Binding DataCollection}" />
</Page.Resources>
....
<ComboBox 
    ItemsSource="{Binding DataCollection}"
    SelectedItem="{Binding Path=MyValue, Converter={StaticResource TaxCodeConverter}}" />

edit: добавленополный IValueConvert вычитал код Convert и ConvertBack

1 Ответ

1 голос
/ 21 октября 2019

Как и BindingProxy, он должен быть Freezable . Кроме того, не передавайте новую наблюдаемую коллекцию в свои метаданные. Это ссылочный тип, поэтому все экземпляры этого конвертера будут инициализированы одним и тем же фактическим экземпляром коллекции.

Дайте мне знать, если вы столкнетесь с какой-то другой проблемой, но я сделал это и смог привязать к свойству зависимости.

Многие утверждают, что лучшим подходом будет использование мультисвязывания и многозначного преобразователя. Я думаю, что имеет смысл иметь строго типизированное свойство с описательным именем.

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 будет таким же, как у вас в вопросе: привязайте свойство зависимостей, и привязка обновит это свойство этого экземпляра MyConverter, при условии, что DataContext вашей страницы имеет соответственнотипизированное свойство с именем DataCollection.

<Page.Resources>
    <converter:MyConverter x:Key="Converter" MyCollection="{Binding DataCollection}" />
</Page.Resources>
...