在绑定中进行转换时,转换器不起作用

时间:2019-07-02 17:46:13

标签: wpf binding converters

我有一个自定义的Treeview控件,并且将控件属性SelectedTreeItem绑定到viewmodel中的对象SelectedItem属性,当将SelectedItem类型设置为object时,没有红色验证边框,但是将SelectedItem类型用作Model时我得到这个红色边框。 取消选择一个从控件到视图模型返回null的项目后,就会出现此边框。

通过一些研究,我发现这是由于两者的类型不同,并且需要在绑定中使用转换器,所以我使用了转换器

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;
        }
      }

即使使用此转换器,我也会遇到相同的问题 ,我做错了什么?red line

2 个答案:

答案 0 :(得分:0)

尝试使用ValueConverter绑定到TreeView控件的选定项没有任何意义,因为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;
    }
}

然后可以将其添加到xaml中用于视图的标准TreeView控件中。

<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>

有关如何在WPF / MVVM中处理TreeView控件的更多详细讨论,请看我的blog post

答案 1 :(得分:-1)

该问题是由于从控件向视图模型返回null时,在ConvertBack中未进行转换。

    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;
    }
}