none
ListViewのDetails表示のFullRowSelectで複数選択時のチェックボックスの挙動 RRS feed

  • 質問

  • お世話になっております。
    今回初めて投稿させていただきます。

    件名の件なのですが、下記コード(新しいプロジェクト→Windowsアプリケーション→Form1.cs)において実行すると、
    「あ」をクリックして次にshift(Ctrl)を押しながら「お」を押す時と
    「あ」をクリックして次にshift(Ctrl)を押しながら「こ」or「そ」を押す時とで
    チェックボックスの挙動が違うのですが、これはこういう仕様なのでしょうか?

    私は複数選択しただけでチェックボックスのチェックを付けたりはずしたりしたくないのですが、
    何か方法はないものでしょうか?

    -----以下コード-----
    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel;  
    using System.Data;  
    using System.Drawing;  
    using System.Text;  
    using System.Windows.Forms;  
     
    namespace WindowsApplication1  
    {  
        public partial class Form1 : Form  
        {  
            public Form1()  
            {  
                InitializeComponent();  
                ListView lv = new ListView();  
                lv.View = View.Details;  
                ColumnHeader ch1 = new ColumnHeader();  
                ch1.Text = "あ行";  
                ch1.Width = 100;  
                ColumnHeader ch2 = new ColumnHeader();  
                ch2.Text = "か行";  
                ch2.Width = 100;  
                ColumnHeader ch3 = new ColumnHeader();  
                ch3.Text = "さ行";  
                ch3.Width = 100;  
                lv.Columns.AddRange(new ColumnHeader[] { ch1, ch2, ch3 });  
                ListViewItem lvi1 = new ListViewItem(new string[] { "あ""か""さ" });  
                ListViewItem lvi2 = new ListViewItem(new string[] { "い""き""し" });  
                ListViewItem lvi3 = new ListViewItem(new string[] { "う""く""す" });  
                ListViewItem lvi4 = new ListViewItem(new string[] { "え""け""せ" });  
                ListViewItem lvi5 = new ListViewItem(new string[] { "お""こ""そ" });  
                lv.Items.AddRange(new ListViewItem[] { lvi1, lvi2, lvi3, lvi4, lvi5 });  
                lv.CheckBoxes = true;  
                lv.Dock = DockStyle.Fill;  
                lv.FullRowSelect = true;  
                this.Controls.Add(lv);  
            }  
        }  
    }  
     

    2009年2月5日 3:17

回答

すべての返信

  • かなり以前(2002年ごろ?)からある問題ですが、未だに未解決のようですね。

    ListView with multiple columns checks the CheckBoxes on multiselection
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=116181


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク BlackTomato 2009年2月9日 2:43
    2009年2月5日 6:58
    モデレータ
  •  返信ありがとうございます。
    昔からほったらかしの問題なんですね。
    チェック変更されるタイミングもちょっとおかしいんですよね。
    マウスを離してからチェック変更されるんですが、
    チェック変更されてからMouseUpとMouseClickイベントが発生するみたいです。
    MouseDown→左ボタンを離す→ItemCheck→MouseClick→MouseUp
    関係ありそうなイベントを拾ってみたんですが、ItemCheckの前に来るイベントはありませんでした。
    2009年2月5日 7:33
  • MouseDownとItemCheckの間にItemSelectionChangedイベントがあったのでちょっとやってみました。
    これでどうでしょう。

    -----以下コード----


        public class MyListView : System.Windows.Forms.ListView  
        {  
            private bool    _checkEnable    = true;  
            private bool    _onMouseDown    = false;  
     
            protected override void OnMouseDown ( System.Windows.Forms.MouseEventArgs e )  
            {  
                // マウスダウンフラグOn  
                this._onMouseDown = true;  
     
                base.OnMouseDown( e );  
            }  
     
            protected override void OnItemSelectionChanged ( System.Windows.Forms.ListViewItemSelectionChangedEventArgs e )  
            {  
                if ( true == this._onMouseDown )  
                {  
                    // チェック状態変更禁止フラグOn  
                    this._checkEnable = false;  
                }  
     
                base.OnItemSelectionChanged( e );  
            }  
     
            protected override void OnItemCheck ( System.Windows.Forms.ItemCheckEventArgs ice )  
            {  
                if ( false == this._checkEnable )  
                {  
                    // チェック状態変更イベントキャンセル  
                    ice.NewValue = ice.CurrentValue;  
                    return;  
                }  
     
                base.OnItemCheck( ice );  
            }  
     
            protected override void OnMouseUp ( System.Windows.Forms.MouseEventArgs e )  
            {  
                // フラグOff  
                this._checkEnable = true;  
                this._onMouseDown = false;  
     
                base.OnMouseUp( e );  
            }  
        } 
    • 回答の候補に設定 BlackTomato2 2009年3月12日 2:46
    2009年3月11日 12:27
  •  お世話になります。BlackTomatoです。
    アカウントのメールアドレスを忘れてしまい、名前が変わりました。

    catsmasterさん返信ありがとうございます。

    if ( false == this._checkEnable )
    の部分を
    if ( false == this._checkEnable  || this.SelectedItems.Count > 1)
    に変えたら理想の動きになりました。

    ItemSelectionChangedイベントは未確認でした。

    ありがとうございました。
    2009年3月12日 2:47
  • 最終的なソースはこうなりました。
    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel;  
    using System.Data;  
    using System.Drawing;  
    using System.Text;  
    using System.Windows.Forms;  
     
    namespace WindowsApplication1  
    {  
        public partial class Form1 : Form  
        {  
            MyListView lv;  
            public Form1()  
            {  
                InitializeComponent();  
                lv = new MyListView();  
                lv.View = View.Details;  
                ColumnHeader ch1 = new ColumnHeader();  
                ch1.Text = "あ行";  
                ch1.Width = 100;  
                ColumnHeader ch2 = new ColumnHeader();  
                ch2.Text = "か行";  
                ch2.Width = 100;  
                ColumnHeader ch3 = new ColumnHeader();  
                ch3.Text = "さ行";  
                ch3.Width = 100;  
                lv.Columns.AddRange(new ColumnHeader[] { ch1, ch2, ch3 });  
                ListViewItem lvi1 = new ListViewItem(new string[] { "あ", "か", "さ" });  
                ListViewItem lvi2 = new ListViewItem(new string[] { "い", "き", "し" });  
                ListViewItem lvi3 = new ListViewItem(new string[] { "う", "く", "す" });  
                ListViewItem lvi4 = new ListViewItem(new string[] { "え", "け", "せ" });  
                ListViewItem lvi5 = new ListViewItem(new string[] { "お", "こ", "そ" });  
                lv.Items.AddRange(new ListViewItem[] { lvi1, lvi2, lvi3, lvi4, lvi5 });  
                lv.CheckBoxes = true;  
                lv.Dock = DockStyle.Fill;  
                lv.FullRowSelect = true;  
     
                ContextMenu cm = new ContextMenu();  
                MenuItem mi1 = new MenuItem("check");  
                mi1.Click += new EventHandler(mi1_Click);  
                MenuItem mi2 = new MenuItem("uncheck");  
                mi2.Click += new EventHandler(mi2_Click);  
                cm.MenuItems.Add(mi1);  
                cm.MenuItems.Add(mi2);  
     
                lv.ContextMenu = cm;  
     
                this.Controls.Add(lv);  
            }  
     
            void mi1_Click(object sender, EventArgs e)  
            {  
                lv.MenuCheck = true;  
                foreach (ListViewItem lvi in lv.SelectedItems)  
                {  
                    lvi.Checked = true;  
                }  
                lv.MenuCheck = false;  
            }  
            void mi2_Click(object sender, EventArgs e)  
            {  
                lv.MenuCheck = true;  
                foreach (ListViewItem lvi in lv.SelectedItems)  
                {  
                    lvi.Checked = false;  
                }  
                lv.MenuCheck = false;  
            }  
        }  
        public class MyListView : System.Windows.Forms.ListView  
        {  
            private bool _checkEnable = true;  
            private bool _onMouseDown = false;  
            private bool _menuCheck = false;  
     
            public bool MenuCheck  
            {  
                set  
                {  
                    _menuCheck = value;  
                }  
            }  
            protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)  
            {  
                // マウスダウンフラグOn     
                this._onMouseDown = true;  
     
                base.OnMouseDown(e);  
            }  
     
            protected override void OnItemSelectionChanged(System.Windows.Forms.ListViewItemSelectionChangedEventArgs e)  
            {  
                if (true == this._onMouseDown)  
                {  
                    // チェック状態変更禁止フラグOn  
                    this._checkEnable = false;  
                }  
     
                base.OnItemSelectionChanged(e);  
            }  
     
            protected override void OnItemCheck(System.Windows.Forms.ItemCheckEventArgs ice)  
            {  
                if (!_menuCheck && (false == this._checkEnable || (this._checkEnable && this.SelectedItems.Count > 1)))  
                {  
                    // チェック状態変更イベントキャンセル     
                    iceice.NewValue = ice.CurrentValue;  
                    return;  
                }  
     
                base.OnItemCheck(ice);  
            }  
     
            protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)  
            {  
                // フラグOff     
                this._checkEnable = true;  
                this._onMouseDown = false;  
     
                base.OnMouseUp(e);  
            }  
        }  
    返信くださった皆様ありがとうございました。
    2009年3月12日 4:29