我熟悉wpf中数据绑定的基础知识。但是我现在有一个问题,我想知道如何解决。
想象一下以下用例:
我有一个名为“AItems”的全局ObservableCollection,类型为A.
我有一些B类对象,每个对象都有一个类型为A的ObservableCollection“BItems”
BItems集合可以包含全局AItems集合的对象。
我希望通过ListView将其可视化 每行应包含一个A-Object和一个复选框 我希望ListView显示AItems-Collection的所有元素。分配给B-Object的项目应使用选中的复选框进行标记。应取消选中所有其他复选框。
我现在的问题是:
我该如何设置datacontext?
如何选中复选框将其项目插入BItems-Collection并取消选中将其删除?
我希望任何人都能理解我的问题。
感谢您的回复。
答案 0 :(得分:3)
我不清楚你问题的后半部分。部分原因是因为你的命名惯例令人困惑;我希望名为BItems
的集合包含B
类型的对象,而不是A
。
所以我会稍微改变你的命名,这样我就不会感到困惑。我将调用第一个班级A
,而不是User
,而不是B
,我将调用第二个班级Group
。 Group
包含User
个对象的集合,名为Users
。全局集合看起来像这样:
List<User> Users;
List<Group> Groups;
很容易确定给定的User
u
是否在任何群组中:
return Groups.Where(g => g.Users.Contains(u)).Any();
如果您有许多群组并且包含许多用户,则很容易,但计算成本很高。我们将在一秒钟内回到那里。
马上,我发现你的一个问题出了问题:
如何选中复选框将其项目插入BItems-Collection并取消选中将其删除?
如果我检查未经检查的用户会怎么样?应该将哪个组(或组,因为多个组可以包含用户)添加到?
既然你说要将选中的项目“分配给B-Object”,我将假设UI一次仅查看一个组 - 我们将其称为{{1 }}。这很好,因为SelectedGroup
比我上面显示的查询便宜得多。
如果是这样,那么您需要做的是将g.Users.Contains(u)
包装在一个公开User
属性的类中。我打电话给这个班级IsChecked
,因为那就是它。该类需要三个属性(至少):
UserViewModel
您的public User User { get; set; }
public Group SelectedGroup { get; set; }
public bool IsChecked
{
get { return SelectedGroup.Users.Contains(this.User); }
set
{
if (value != IsChecked)
{
if (IsChecked)
{
SelectedGroup.Users.Remove(this.User);
}
else
{
SelectedGroup.Users.Add(this.User);
}
}
}
}
绑定了一个ListView
,名为ObservableCollection<UserViewModel>
。每当设置UserViewModels
时,您需要重建此集合:
SelectedGroup
您可以通过在UserViewModels = new ObservableCollection<UserViewModel>(
Users.Select(u => new UserViewModel { User=u, SelectedGroup=SelectedGroup }));
课程中实施INotifyPropertyChanged
来避免重建该集合,并在UserViewModel
更改时让PropertyChanged
属性为IsChecked
。
此外,它可能负责在SelectedGroup
属性中包含空引用检查,以便在IsChecked
或SelectedGroup
为空时程序不会引发异常。
答案 1 :(得分:0)
您可以将列表框绑定到Aitems并使用转换器设置isChecked属性
<ListBox ItemsSource="{Binding AItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}" IsChecked="{Binding Mode=OneTime, Converter={StaticResource BItemCheckConverter}}"></CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
public class BItemCheckConverter : IValueConverter
{
public List<Aitems> BItems { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (BItems.Contains((value as Aitems)) return true;
else return false
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
我不知道你的对象模型是怎样的,所以按原样使用上面的代码。
HTH