How can I find if a selection is inside the rubberband selection in a ListView?

让人想犯罪 __ 提交于 2019-12-11 15:32:57

问题


I am using the events ItemSelectionChanged and SelectedIndexChanged of the ListView class to answer this question.

The code is below, and the only bug that seems to remain is that I use the 250ms timer also when the user uses rubberband selection, not only for single or double click selection.

internal Form1()
{
    InitializeComponent();

    t.Tick += T_Tick;
}

internal bool santinela = false;

internal void T_Tick(object sender, EventArgs e)
{
    t.Stop();

    if (!santinela)
    {
        bool newVal = selectionChangedItem.Selected;

        selectionChangedItem.Checked =
            selectionChangedItem.Selected = newVal;

        santinela = true;
    }
}

internal Timer t = new Timer()
{
    Interval = 250
};

internal bool santinela3 = true;

internal void listView1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    if (santinela3)
    {
        if (e.CurrentValue == CheckState.Checked)
        {
            listView1.SelectedIndices.Remove(e.Index);
        }
        else if (e.CurrentValue == CheckState.Unchecked)
        {
            listView1.SelectedIndices.Add(e.Index);
        }
    }
}

internal void listView1_ItemActivate(object sender, EventArgs e)
{
    if (listView1.SelectedItems.Count > 0)
    {
        MessageBox.Show(listView1.SelectedItems[0].Text);
    }
}

internal ListViewItem selectionChangedItem = null;

internal bool santinela2 = true;

internal void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
    if (!santinela2)
    {
        return;
    }

    if (t.Enabled)
    {
        santinela = true;

        t.Stop();

        // double click: both clicks must be done in the same place
        if (e.Item == selectionChangedItem)
        {
            if (!e.IsSelected)
            {
                santinela2 = true;

                e.Item.Selected = true;

                santinela2 = false;
            }

            listView1_ItemActivate(sender, EventArgs.Empty);
        }

        selectionChangedItem = null;
    }
    else
    {
        santinela = false;

        t.Stop();

        selectionChangedItem = e.Item;

        t.Start();
    }
}

internal void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (listView1.SelectedIndices.Count == 0)
    {
        santinela = true;

        t.Stop();

        selectionChangedItem = null;


        santinela3 = false;
        for (int i = 0; i < listView1.CheckedItems.Count; ++i)
        {
            listView1.CheckedItems[i].Checked = false;
        }
        santinela3 = true;
    }
}

The relevant designer code is below:

System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("item1");
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("item2");
this.listView1 = new System.Windows.Forms.ListView();
this.SuspendLayout();
// 
// listView1
// 
this.listView1.CheckBoxes = true;
listViewItem1.StateImageIndex = 0;
listViewItem2.StateImageIndex = 0;
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2});
this.listView1.Location = new System.Drawing.Point(12, 12);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(401, 327);
this.listView1.TabIndex = 0;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.ItemActivate += new System.EventHandler(this.listView1_ItemActivate);
this.listView1.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.listView1_ItemCheck);
this.listView1.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listView1_ItemSelectionChanged);
this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);

Update: The issue I am facing because of the timer is that after hovering with the rubberband a ListViewItem, there is the useless delay of the timer before the item gets checked. When the user resizes/moves the rubberband so that the ListViewItem is no longer checked, there is the same delay. If the user does not know of that non-standard delay, the selection can be wrong.

来源:https://stackoverflow.com/questions/54237368/how-can-i-find-if-a-selection-is-inside-the-rubberband-selection-in-a-listview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!