業務のためのC#・C言語・C++学習

主にC#の文法やWPF周りのアウトプットに利用してます。

【C#-WPF】ListviewのヘッダーにCheckBoxを追加しチェックした場合、全Itemがチェックされる。アンチェックした場合、全Itemを解除する。

前回WPFにおいて、「ListViewにCheckBoxを追加するには」について取り上げました。 gaishiengineer.hatenablog.com

今回は上記のUIにListViewのヘッダーにCheckBoxを追加し全ItemのCheckとUnCheckを行います。 コードが長くなるので2段階に分けて説明します。 1段階目はListViewコレクションの全要素をセレクトする、2段階目でセレクトした全要素のCheckBoxのCheckを変更していきます。

UI 段階1

まずListViewコレクションの要素をCastつまり青い選択された状態にする。 ListViewのヘッダーにあるCheckBoxをCheckすると全要素がセレクトされる。一方、CheckBoxがCheckされた状態でCheckを外すと全Itemのセレクトが外れるようにします。

XAML

<Window x:Class="Listview_checkbox.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:Listview_checkbox"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Margin="-1,65,0.6,0">
        <Button Content="Button" HorizontalAlignment="Left" Margin="21,-41,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <ListView Name="ListViewName">
            <ListView.View>
                <GridView>

                    <!--最初の列にCheckBocを追加する-->
                    <GridViewColumn >
                        <GridViewColumn.Header>
                            <CheckBox Name="CheckBox_PendingListAll" Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </GridViewColumn.Header>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox Margin="5,0" IsChecked="{Binding Selected}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <GridViewColumn Header="項目1" Width="200" DisplayMemberBinding="{Binding items1}"/>
                    <GridViewColumn Header="項目2" Width="200" DisplayMemberBinding="{Binding items2}"/>
                    <GridViewColumn Header="項目3" Width="200" DisplayMemberBinding="{Binding items3}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;


namespace Listview_checkbox
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //ListView
            List<ListViewItems> items = new List<ListViewItems>();
            items.Add(new ListViewItems() {  Selected = true, items1 = "111", items2 = "222", items3 = "333" });
            items.Add(new ListViewItems() {  Selected = false, items1 = "bbb", items2 = "ccc", items3 = "ddd" });
            items.Add(new ListViewItems() {  Selected = true, items1 = "BBB", items2 = "CCC", items3 = "DDD" });
            ListViewName.ItemsSource = items;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            
        }

        private void chkSelectAll_Checked(object sender, RoutedEventArgs e)
        {   
            foreach (ListViewItems item in ListViewName.ItemsSource)
            {
                ListViewName.SelectedItems.Add(item);
            }
        }

        private void chkSelectAll_Unchecked(object sender, RoutedEventArgs e)
        {
                foreach (ListViewItems item in ListViewName.ItemsSource)
                {
                    ListViewName.SelectedItems.Remove(item);
                }
        }
    }

    public class ListViewItems
    {
        public bool Selected { get; set; }
        public string items1 { get; set; }
        public string items2 { get; set; }
        public string items3 { get; set; }
    }
}

解説

ListViewのヘッダーにCheckBoxを配置し、CheckとUnCheckしたときのメソッドを追加する。

<GridViewColumn.Header>
  <CheckBox Name="CheckBox_PendingListAll" Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked" HorizontalAlignment="Center"        VerticalAlignment="Center"/>
</GridViewColumn.Header>

chkSelectAll_Checkedが実行されれば foreachを用いListViewName.ItemsSourceにある全要素取り出し、 ListViewName.SelectedItems.Add(item)を実行。 chkSelectAll_Uncheckedが実行されれば foreachを用いListViewName.ItemsSourceにある全要素取り出し、 ListViewName.SelectedItems.Remove(item);を実行。

UI 段階2

ListViewヘッダーのCheckBoxをCheckすると全アイテムがCheckされる、UnCheckされる

XAML

<Window x:Class="Listview_checkbox.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:Listview_checkbox"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Margin="-1,65,0.6,0">
        <Button Content="Button" HorizontalAlignment="Left" Margin="21,-41,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        <ListView Name="ListViewName" SelectionChanged="ListViewName_SelectionChanged">
            <ListView.View>
                <GridView>

                    <!--最初の列にCheckBocを追加する-->
                    <GridViewColumn >
                        <GridViewColumn.Header>
                            <CheckBox Name="CheckBox_PendingListAll" Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </GridViewColumn.Header>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox Margin="5,0" IsChecked="{Binding Selected}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

                    <GridViewColumn Header="項目1" Width="200" DisplayMemberBinding="{Binding items1}"/>
                    <GridViewColumn Header="項目2" Width="200" DisplayMemberBinding="{Binding items2}"/>
                    <GridViewColumn Header="項目3" Width="200" DisplayMemberBinding="{Binding items3}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Windows;

namespace Listview_checkbox
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            //ListView
            List<ListViewItems> items = new List<ListViewItems>();
            items.Add(new ListViewItems() { /*items = "000",*/ Selected = true, items1 = "111", items2 = "222", items3 = "333" });
            items.Add(new ListViewItems() { /*items = "aaa",*/ Selected = false, items1 = "bbb", items2 = "ccc", items3 = "ddd" });
            items.Add(new ListViewItems() { /*items = "AAA",*/ Selected = true, items1 = "BBB", items2 = "CCC", items3 = "DDD" });
            ListViewName.ItemsSource = items;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

        }

        private void chkSelectAll_Checked(object sender, RoutedEventArgs e)
        {

            foreach (ListViewItems item in ListViewName.ItemsSource)
            {

                ListViewName.SelectedItems.Add(item);
            }
        }

        private void chkSelectAll_Unchecked(object sender, RoutedEventArgs e)
        {

            foreach (ListViewItems item in ListViewName.ItemsSource)
            {

                ListViewName.SelectedItems.Remove(item);
            }

        }

        private void ListViewName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                //------------
                ListViewItems user = (ListViewItems)e.AddedItems[0];
                ListViewItem lvi = (ListViewItem)ListViewName.ItemContainerGenerator.ContainerFromItem(user);
                CheckBox chkBx = FindVisualChild<CheckBox>(lvi);
                if (chkBx != null)
                    chkBx.IsChecked = true;
                //------------              
            }
            else // Remove Select All chkBox
            {
                ListViewItems user = (ListViewItems)e.RemovedItems[0];
                ListViewItem lvi = (ListViewItem)ListViewName.ItemContainerGenerator.ContainerFromItem(user);
                CheckBox chkBx = FindVisualChild<CheckBox>(lvi);
                if (chkBx != null)
                    chkBx.IsChecked = false;
            }

        }

        public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T)
                    {
                        return (T)child;
                    }

                    T childItem = FindVisualChild<T>(child);
                    if (childItem != null) return childItem;
                }
            }
            return null;
        }


    }

    public class ListViewItems
    {
        //public string items { get; set; }
        public bool Selected { get; set; }
        public string items1 { get; set; }
        public string items2 { get; set; }
        public string items3 { get; set; }
    }
}

解説

ListViewでSelectとされた要素に変更を与えるメソッド ListViewName_SelectionChangedをXAMLとMainWindowに追加します。 すでに段階1で記載したchkSelectAll_checkedとchkSelectAll_Uncheckedで全アイテムのSelect変更が行われその次に ListViewName_SelectionChangedが実行されます。

<ListView Name="ListViewName" SelectionChanged="IvTestItems_SelectionChanged">
            <ListView.View>

ListViewName_SelectionChangedの実装をもってすべてのCheckBoxをCheckまたはUnCheckします。

次回

ListViewのCheckBoxでCheckされた項目を選択しメソッドを実行する

gaishiengineer.hatenablog.com