Конвертер не работает при конвертации в привязку - PullRequest
0 голосов
/ 02 июля 2019

У меня есть пользовательский древовидный элемент управления, и я привязываю свойство элемента управления SelectedTreeItem, которое является типом объекта, к свойству SelectedItem в viewmodel. При установке типа SelectedItem в качестве объекта отсутствует красная граница проверки, но при использовании типа SelectedItem в качестве модели я получаю эту красную границу. Эта граница появляется после отмены выбора элемента, который возвращает ноль из элемента управления в viewmodel.

По результатам некоторых исследований я обнаружил, что это связано с тем, что оба типа являются разными, и в привязке необходимо использовать конвертер, поэтому я использовал конвертер

XAML:

SelectedTreeItem="{Binding SelectedItem, Mode=TwoWay,Converter={StaticResource selectedItemConverter}}"

Свойство ViewModel:

        private Model selectedItem;

        public Model SelectedItem
        {
            get 
            { 
                return selectedItem; 
            }
            set 
            { 
                selectedItem = value;
                this.RaisePropertyChanged(() => this.SelectedItem);
            }
        }

Преобразователь:

    public class SelectedItemConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            object obj = null;
            obj = (value as object);
            return obj;
        }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
      }

Даже с этим конвертером у меня та же проблема что я делаю не так? красная линия

Ответы [ 2 ]

0 голосов
/ 03 июля 2019

Нет смысла пытаться привязать выбранный элемент элемента управления TreeView с помощью ValueConverter, поскольку SelectedItem является свойством только для чтения.

Такая функциональность может быть реализована с использованием класса Behavior, например,

public class perTreeViewHelper : Behavior<TreeView>
{
    public object BoundSelectedItem
    {
        get => GetValue(BoundSelectedItemProperty);
        set => SetValue(BoundSelectedItemProperty, value);
    }

    public static readonly DependencyProperty BoundSelectedItemProperty =
        DependencyProperty.Register("BoundSelectedItem",
            typeof(object),
            typeof(perTreeViewHelper),
            new FrameworkPropertyMetadata(null,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnBoundSelectedItemChanged));

    private static void OnBoundSelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue is perTreeViewItemViewModelBase item)
            item.IsSelected = true;
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        base.OnDetaching();
    }

    private void OnTreeViewSelectedItemChanged(object obj, RoutedPropertyChangedEventArgs<object> args)
    {
        BoundSelectedItem = args.NewValue;
    }
}

Затем его можно добавить к стандартному элементу управления TreeView в xaml для вашего просмотра.

<TreeView Grid.Column="0" ItemsSource="{Binding RootItemVms}">
    <i:Interaction.Behaviors>
        <vhelp:perTreeViewHelper BoundSelectedItem="{Binding SelectedItem}" />
    </i:Interaction.Behaviors>

    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:ItemVm}" ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal">
                <CheckBox
                    VerticalAlignment="Center"
                    Focusable="False"
                    IsChecked="{Binding IsChecked, Mode=TwoWay}" />
                <TextBlock
                    Margin="4,0,8,0"
                    VerticalAlignment="Center"
                    Text="{Binding Caption}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

Более подробное обсуждение того, как работать с элементами управления TreeView в WPF / MVVM, можно найти в моем моем блоге .

0 голосов
/ 02 июля 2019

Проблема заключалась в том, что в ConvertBack не выполнялось преобразование при возврате значения null из элемента управления в viewmodel.

    public class SelectedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value as Model;
    }
}
...