2014-06-10 19 views
6

我正在使用C#和WPF,并且我有一个ListView用于在第一列中包含CheckBox。 ListView的ItemsSource在代码中设置(不通过绑定),并包含属性“Name”,“Type”和“Selected”的类“Item”的实例。带有分组项目的ListView - 通过组标题选择所有组成员复选框

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中 - 例如复选框表示被“选中”。

我正在将此分组添加到此ListView(按'类型'分组),并且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")); 

的XAML为ListView包含在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> 

最后对我的问题:我想发生这样的是可以使用复选框的组标题以选择该特定组中的所有项目或全部项目。例如:

Example

点击组头复选框,如果他们还没有选择在那个特定的群体应选择所有项目。再次单击它应该取消选择(取消选中)该组中的所有项目。如果用户手动选择或取消选择组中的某些项目,最好使组标题复选框显示不确定状态,但仅仅取消选中状态也不错。

我不知道从哪里开始。我假设我需要绑定组头的IsChecked属性复选框,但我不知道要绑定到什么,因为datacontext是某种GroupDescriptor,它不包含有关该组的任何信息,也不是该组中有哪些项目(对吗?)。

我不严格遵循MVVM,所以我不担心在绑定和我的viewmodel中完成所有事情,我会很好地听取复选框的Checked事件,并以某种方式在代码中找出哪些项目应该检查。例如;如果我可以听取Checked事件并以某种方式提取组的类型,我将大部分设置(我可以遍历整个列表并选择所有具有匹配组的组)。但我甚至没有看到这样做的方式;我可以在Checked事件(发件人)中获得CheckBox,并且我可以循环到所有父级控件,但是在任何地方我都看不到提取有关我正在分组的属性的信息...

Any帮助会很棒!

回答

0

您可以处理何时检查组标题,然后遍历组中的项目并将IsChecked设置为true。

+0

但是,如何获得组中的项目?我需要知道我正在分组的属性的价值,或者以其他方式获取组项目,我找不到任何方法获取它们。 –

2

我想通了,我需要的只是CheckBox的DataContext。这不是最好的解决方案(当然不是MVVM),但它似乎工作正常。

只需将Checked和Unchecked事件处理程序添加到组风格的复选框中,将DataContext转换为包含项目的CollectionViewGroup。

在的情况下,嵌套的分组项目集合包含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; 
      } 
     } 
    } 

现在我还需要弄清楚如何响应检查项目并更改相应组中的复选框。

+0

你有没有想出这个解决方案? – SZT

相关问题