WPF绑定复选框列表,其中选中的复选框绑定到列表的成员

WPF绑定复选框列表,其中选中的复选框绑定到列表的成员,wpf,xaml,checkbox,binding,member,Wpf,Xaml,Checkbox,Binding,Member,所以我有一个所有可能值的列表,和一个只发生一次的发生值的列表。与[A,B,C,D,E]和[D,A]一样,第二个列表的每个元素也必须是第一个列表的成员 我想创建一个listview,每个可能的值一行,其中每行都是一个复选框,将内容绑定到值的名称,并被选中为occuringValues.contains(可能值)。在我的示例中,这看起来像: [x] A [ ] B [ ] C [x] D [ ] E 选中或取消选中复选框应在“出现值”列表中添加或删除元素 我尝试过很多方法,但运气不好,比如

所以我有一个所有可能值的列表,和一个只发生一次的发生值的列表。与[A,B,C,D,E]和[D,A]一样,第二个列表的每个元素也必须是第一个列表的成员

我想创建一个listview,每个可能的值一行,其中每行都是一个复选框,将内容绑定到值的名称,并被选中为occuringValues.contains(可能值)。在我的示例中,这看起来像:

[x] A

[ ] B

[ ] C

[x] D

[ ] E
选中或取消选中复选框应在“出现值”列表中添加或删除元素

我尝试过很多方法,但运气不好,比如:

使用字符串和bool(用于IsChecked)以及ObservableCollection创建INotifyPropertyChanged实现帮助器类可以控制类中的更改,但是类中的更改不会触发ObservableCollection的set函数,否则我可能会更新那里的[D,a]列表


我可以改变我的GUI使事情变得更简单,列出发生的值并创建一个包含可能值的组合框,但是如果你有想法的话,我更喜欢使用复选框

所以我在安德鲁斯建议的启发下设法解决了这个问题

我添加了一个包装类,如下所示:

class MyOccExpLimitComment
{
    private ObservableCollection<OccupationalExposureLimitComment> Occuring;

    public MyOccExpLimitComment(ObservableCollection<OccupationalExposureLimitComment> occuring, OccupationalExposureLimitComment inner)
    {
        Occuring = occuring;
        Inner = inner;
    }

    public OccupationalExposureLimitComment Inner { get; set; }
    public bool IsChecked
    {
        get
        {
            return Occuring.Contains(Inner);
        }
        set
        {
            if (value == false)
            {
                if (Occuring.Contains(Inner))
                    Occuring.Remove(Inner);
            }
            else
                if (!Occuring.Contains(Inner))
                    Occuring.Add(Inner);

        }
    }
}
class-myocexplimitcomment
{
发生私人可观察到的收集;
public MyoceCExplimitComment(可观察到的收藏发生,职业曝光限制Comment内部)
{
发生=发生;
内部=内部;
}
public OccupationExposureLimitComment内部{get;set;}
公共场所被检查
{
得到
{
返回发生。包含(内部);
}
设置
{
如果(值==false)
{
如果(发生包含(内部))
发生。移除(内部);
}
其他的
如果(!Occuring.Contains(内部))
发生。添加(内部);
}
}
}
XAML:


财产:

    private ObservableCollection<MyOccExpLimitComment> myOccExpLimitComments;
    public ObservableCollection<MyOccExpLimitComment> MyOccExpLimitComments
    {
        get
        {
            if (myOccExpLimitComments == null)
                myOccExpLimitComments = new ObservableCollection<MyOccExpLimitComment>(AvailableOccExpLimitComments.Select(c => new MyOccExpLimitComment(OccExpLimitComments, c)));
            return myOccExpLimitComments;
        }

    }
private observeCollection myocexplimitcomments;
公众可观察的收集意见
{
得到
{
if(myoceXPLimitComments==null)
myOccExpLimitComments=newobservecollection(可用的accexplimitcomments.Select(c=>newmyoccexplimitcomments(OccExpLimitComments,c));
返回myocexplimitcomments;
}
}

因此,我的集合中的每个元素都通过对集合的发生引用知道它在集合中的存在,并在选中/取消选中框时使用setter更新集合。

在哪里使用“发生”列表?您是否也将其绑定到某种UI列表控件?如果是,是否希望在第一个列表中选中/取消选中项目时更新此列表?发生列表仅显示在此复选框列表中,它不在gui中的任何其他位置使用,但已连接到数据库,因此用户必须能够选中一个框,单击“保存”,并在数据库中添加元素。当然,我可以在保存时手动阅读它,但我更喜欢以一种很好的mvvm方式声明性地添加它,而不是强制/手动地添加它。也许我误解了一些东西,但感觉你把事情复杂化了。当您使用MVVM时,我假设您的listview绑定到一个对象集合(例如“Customer”类)。标准方法是向该类添加布尔属性(例如“IsSelected”),并将复选框
IsChecked
绑定到此类。单击“保存”时,只需遍历集合并检查每个对象的IsSelected属性,以确定它是否已在UI中被选中。我了解您的观点以及您的来源。然而,我将直接绑定到我的实体框架实体(db优先),只要我可以。我知道很多人认为这是把VM和M混为一谈,但对我来说,这似乎是一个避免实质上重写实体并做大量锅炉板代码的好方法。有些情况下,我的VM属性比仅仅连接到M更复杂,我可以按照你的建议那样解决它,但如果可能的话,我想避免它。我在这里做的不是将整个实体“复制”为一个模型,而是创建一个模型类,作为实体的包装器。将实体本身作为属性公开(因此您仍然可以绑定到其属性),然后根据您的V/VM的需要将任何其他属性添加到模型中,例如
IsSelected
属性。这很接近,但有一个不幸的副作用,即未勾选的元素不再出现在列表中(如果使用事件正确更新)更好的方法是跟踪两个集合,一个表示全部元素,另一个只包含选定元素。如果需要更新,这也有助于从数据库中刷新可用元素。
    private ObservableCollection<MyOccExpLimitComment> myOccExpLimitComments;
    public ObservableCollection<MyOccExpLimitComment> MyOccExpLimitComments
    {
        get
        {
            if (myOccExpLimitComments == null)
                myOccExpLimitComments = new ObservableCollection<MyOccExpLimitComment>(AvailableOccExpLimitComments.Select(c => new MyOccExpLimitComment(OccExpLimitComments, c)));
            return myOccExpLimitComments;
        }

    }