Wpf listview стиль заголовка флажок threestate
Привет,
Я застрял на том, чтобы сделать флажок threestate.
Я создал образец, как показано ниже. Когда дочерние элементы выбранного родительского флажка должна показать проверка/снимите/Indetermine
Может ли кто-нибудь помочь в приведенном ниже коде, чтобы заставить его работать threestate of checkbox?
Заранее спасибо.
Что я уже пробовал:
Окна.язык XAML:
<Window x:Class="SampleLV.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:SampleLV" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <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}" Checked="CheckBox_Checked" /> </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 x:Name="exp" IsExpanded="True"> <Expander.Header> <StackPanel Orientation="Horizontal"> <CheckBox Checked="OnGroupChecked" IsThreeState="True" IsChecked="{Binding DataContext.IsSelected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Unchecked="OnGroupUnchecked" Visibility="{Binding }"></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> </Grid> </Window>
Окна.язык XAML.в CS:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace SampleLV { /// <summary> /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); 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")); } private void OnGroupChecked(object sender, RoutedEventArgs e) { this.HandleGroupCheck((CheckBox)sender, true); } 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; } } } private void OnGroupUnchecked(object sender, RoutedEventArgs e) { this.HandleGroupCheck((CheckBox)sender, false); } private void CheckBox_Checked(object sender, RoutedEventArgs e) { this.HandleChildCheck((CheckBox)sender, true); } private void HandleChildCheck(CheckBox sender, bool check) { var group = (Item)sender.DataContext; group.IsSelected = true; } public static T GetVisualParent<t>(Visual referenceVisual) where T:Visual { Visual parent = referenceVisual; while (parent !=null) { parent = VisualTreeHelper.GetParent(parent) as Visual; if(parent !=null && parent.GetType() == typeof(T)) { return parent as T; } } return parent as T; } private void HandleChildGroupCheck(Item 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; // } //} } } 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(); } } bool? _isSelected; public bool? IsSelected { get { return _isSelected; } set { _isSelected = value; OnPropertyChanged("IsSelected"); } } protected virtual void OnPropertyChanged([CallerMemberName] string property = "") { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(property)); } public event PropertyChangedEventHandler PropertyChanged; } }