在WPF中,我如何双向将Checkbox的IsChecked绑定到List属性<> .Contains?

时间:2018-06-12 21:11:14

标签: c# wpf

很抱歉,如果我的问题的措辞不是很好,或者某些问题已在某处得到解答,我已经搜索了,但我真的不知道如何解释我想要做的事情。

这是一个简单的测试平台,我已部分设置以帮助解释:

MainWindow.xaml:

<Window x:Class="wpfExample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:wpfExample"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ListView Grid.Column="0" ItemsSource="{Binding People}" DisplayMemberPath="Name"/>

    <ListBox Grid.Column="1" ItemsSource="{Binding Interests}" Margin="0,4,4,4">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding Name}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Grid>

MainWindow.xaml.cs:

using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace wpfExample
{
    public class Person
    {
        public string Name { get; set; }
        public ObservableCollection<Guid> Interests { get; set; }
    }

    public class Interest
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

    public class Data
    {
        public ObservableCollection<Person> People { get; set; }
        public ObservableCollection<Interest> Interests { get; set; }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            DataContext = new Data
            {
                People = new ObservableCollection<Person>
                {
                    new Person {Name="Fred", Interests=new ObservableCollection<Guid>() },
                    new Person {Name="Jane", Interests=new ObservableCollection<Guid>() },
                    new Person {Name="Zach", Interests=new ObservableCollection<Guid>() }
                },
                Interests = new ObservableCollection<Interest>
                {
                    new Interest {Name="Gardening", Id=Guid.NewGuid() },
                    new Interest {Name="Writing", Id=Guid.NewGuid() },
                    new Interest {Name="Avoiding Tax", Id=Guid.NewGuid() }
                }
            };

            InitializeComponent();
        }
    }
}

所以我有一个包含两个列表的DataContext。一个包含兴趣,其中包含姓名和ID。另一个包含具有姓名和兴趣ID列表的人。

当在UI中选择Person时,我希望能够在各自的列表中添加和删除兴趣ID,因此第1列中的ListView绑定到Interests列表,但是如何正确绑定列表中复选框的IsChecked属性?

在我的完整项目中,我已经能够成功读取所选人员兴趣列表的属性,使用MultiBinding for IsChecked和MultiValueConverter传递兴趣的Id和列表人员的兴趣在一起(因为您不能使用与正常值转换器的参数绑定)。我觉得这个解决方案有点滥用转换器,但如果有必要,我很乐意坚持使用它。

当切换复选框时,如何实现一个系统,允许我在一个人的兴趣列表中添加和删除兴趣指南?这样做有更干净的方法吗?如果可以避免,我不想改变模型。

1 个答案:

答案 0 :(得分:1)

我不会说你的MultiConverter解决方案是滥用的;你正在做的转换器应该是什么(获取一组数据并转换为目标类型,然后返回)。

有人说;由于它们的通用性(object的使用),转换器有点混乱,而且对于多转换器而言,转换器是双倍的,所以如果你想要一个不同的解决方案,我建议创建一个视图模型Interest的包装器;说Selectable<T>

public class Selectable<T>
{
     public T Data {get; set;}
     public bool Selected {get; set;}
}

然后更新你的财产

public ObservableCollection<Selectable<Interest>> Interests { get; set; }

IsChecked直接绑定到Selected

然后,只要更改了所选的Person,您就可以适当地更新Selected属性;将前一个值存储到另一个Person等。这在某种程度上取决于用户操作何时需要反映在模型中。

所有这一切,两种方法都是完全有效的,它只取决于你最满意的。