【问题标题】:In WPF, how do I two-way bind a Checkbox's IsChecked to property to List<>.Contains?在 WPF 中,如何将 Checkbox 的 IsChecked 属性双向绑定到 List<>.Contains?
【发布时间】:2018-06-13 05:20:10
【问题描述】:

对不起,如果我的问题的措辞不是很好,或者如果这已经在某个地方得到了回答,我已经搜索过了,但我真的不知道如何解释我想要做什么。

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

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 中选择了一个人时,我希望能够在他们各自的列表中添加和删除兴趣 ID,因此第 1 列中的 ListView 绑定到兴趣列表,但是我如何正确绑定列表中复选框的 IsChecked 属性?

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

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

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

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

    话虽这么说;由于它们的通用性(使用object),转换器有点混乱,对于多转换器来说,这会加倍,所以如果你想要一个不同的解决方案,我建议你创建一个视图模型包装器Interest;说Selectable&lt;T&gt;

    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 等。这在一定程度上取决于何时需要在模型中反映用户操作。

    话虽如此,这两种方法都是完全有效的,它只是归结为您最喜欢的方法。

    【讨论】:

    • 谢谢,我在我的解决方案中使用了它作为灵感,完全避免使用价值转换器。我想我已经深入尝试让值转换器与绑定参数一起工作,以至于我没有真正考虑过不同的方法。
    猜你喜欢
    • 2016-04-26
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多