我正在使用C#和WPF,我有一个ListView,它在第一列中保存带有CheckBox的项目。 ListView的ItemsSource是在代码中设置的(不是通过绑定),并包含类' Item'的实例。具有属性'名称','类型'和'选择'。
public class Item : INotifyPropertyChanged
{
private string _name;
private bool _selected;
private string _type;
public string Name
{
get { return _name; }
set
{
_name = value;
this.OnPropertyChanged();
}
}
public bool Selected
{
get { return _selected; }
set
{
_selected = value;
this.OnPropertyChanged();
}
}
public string Type
{
get { return _type; }
set
{
_type = value;
this.OnPropertyChanged();
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string property = "")
{
if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
ListView的视图设置为GridView,第一列是绑定到Selected属性的复选框 - 例如复选框表示正在选择'。
我正在为此ListView添加分组(按' Type'分组),GroupStyle也包含CheckBox。
var lst = new List<Item>();
lst.Add(new Item { Name = "A", Type = "1" });
lst.Add(new Item { Name = "B", Type = "1" });
lst.Add(new Item { Name = "C", Type = "1" });
lst.Add(new Item { Name = "A", Type = "2" });
lst.Add(new Item { Name = "B", Type = "2" });
lst.Add(new Item { Name = "C", Type = "2" });
listview.ItemsSource = lst;
var view = CollectionViewSource.GetDefaultView(lst);
view.GroupDescriptions.Add(new PropertyGroupDescription("Type"));
ListView的XAML包含GridView和GroupStyle:
<ListView x:Name="listview">
<!-- View -->
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="cls:Item">
<CheckBox IsChecked="{Binding Selected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="300" Header="Name" DisplayMemberBinding="{Binding Name, UpdateSourceTrigger=PropertyChanged}"></GridViewColumn>
<GridViewColumn Width="100" Header="Type" DisplayMemberBinding="{Binding Type}"></GridViewColumn>
</GridView>
</ListView.View>
<!-- Group style -->
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<CheckBox></CheckBox>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding ItemCount, StringFormat='- {0} item(s)'}" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
最后关于我的问题:我想要发生的是能够使用组标题中的CheckBox来选择该特定组中的所有项目或不选择任何项目。例如:
单击组标题复选框应选择该特定组中的所有项目(如果尚未选中)。再次单击它应该取消选择(取消选中)该组中的所有项目。如果用户手动选择或取消选择组中的某些项目,那么组头复选框显示不确定状态会很好,但只是未选中状态也会很好。
我不知道从哪里开始。我假设我需要绑定组头复选框的IsChecked属性,但我不知道将它绑定到什么,因为datacontext将是某种不包含任何内容的GroupDescriptor。有关该组的信息,以及该组中的项目(右??)。
我并不是严格遵循MVVM,所以我不担心在绑定和我的视图模型中完成所有操作,我会好像听一下复选框的Checked事件并以某种方式在代码中找出应该检查项目。例如;如果我可以收听Checked事件并以某种方式提取组的类型我将主要设置(我可以浏览整个列表并选择所有匹配组的组)。但我甚至没有看到这样做的方法;我可以在Checked事件(发件人)中获取CheckBox,并且我可以循环到所有父控件,但是我无处可去提取有关我分组的属性的信息......
任何帮助都会很棒!
答案 0 :(得分:2)
我想通了,我需要的只是CheckBox的DataContext。它不是最好的解决方案(肯定不是MVVM),但似乎工作正常。
只需将Checked和Unchecked事件处理程序添加到组样式中的复选框,将DataContext强制转换为包含项目的CollectionViewGroup。
如果嵌套分组,Items集合包含另一个CollectionViewGroup实例,那么当您找到另一个(嵌套)组时,需要以递归方式循环遍历这些项:
private void OnGroupChecked(object sender, RoutedEventArgs e)
{
this.HandleGroupCheck((CheckBox)sender, true);
}
private void OnGroupUnchecked(object sender, RoutedEventArgs e)
{
this.HandleGroupCheck((CheckBox)sender, false);
}
private void HandleGroupCheck(CheckBox sender, bool check)
{
var group = (CollectionViewGroup) sender.DataContext;
this.HandleGroupCheckRecursive(group, check);
}
private void HandleGroupCheckRecursive(CollectionViewGroup group, bool check)
{
foreach (var itemOrGroup in group.Items)
{
if (itemOrGroup is CollectionViewGroup)
{
// Found a nested group - recursively run this method again
this.HandleGroupCheckRecursive(itemOrGroup as CollectionViewGroup, check);
}
else if (itemOrGroup is Item)
{
var item = (Item)itemOrGroup;
item.Selected = check;
}
}
}
现在我仍然需要弄清楚如何回复检查项目并更改相应组中的复选框。
答案 1 :(得分:0)
您可以在检查组标题时进行处理,然后遍历组中的项并将IsChecked设置为true。