winforms 取消选中/选中ListViewItem

dm7nw8vv  于 2023-11-21  发布在  其他
关注(0)|答案(2)|浏览(80)

我有一个包含许多项的ListViewItem,默认情况下所有的项都被选中。
我想写一个函数,它将获得需要检查的项目列表。

public void NewCheckSecurities(SecurityList oSecurities)
{
    // error checking 
    if (oSecurities == null || oSecurities.Count == 0)
    {
        return;
    }

    // check sent securities 
    ListView.ListViewItemCollection oItems = m_lsvSecurities.Items;
    if (oItems != null)
    {
        int i = 1;
        foreach (ListViewItem oItem in oItems)
        {
            bool bFind = oSecurities.FindSecurity((oItem.Tag as SecurityItem).Security.Symbol) != null;
            if(bFind)
            {
                oItem.Checked = true;
            }
            else
            {
                oItem.Checked = false;
            }
        }
    }
}

字符串
o证券有5种证券,我想检查。
o项目大小- 2800个项目
为了检查这个问题,我不得不把这个函数拆成2个部分(find,checked)。
第一部分是一个循环,它遍历所有项,并仅使bFind为true或false。
当我把第二部分加上

if(bFind)
            {
                oItem.Checked = true;
            }
            else
            {
                oItem.Checked = false;
            }


但是它工作太慢了。
当代码在做oItem的时候。在oItems中为每个oItem选中true或false是花了很长时间的。
有什么方法可以更快地完成吗?

mctunoxg

mctunoxg1#

该问题很可能是由组件在每次更新后重新绘制自身引起的。
这通常可以通过在您进行更改时告诉Form暂停视觉更新来加速,如下所示:

this.SuspendLayout();

// Do your updates here

this.ResumeLayout();

字符串
它应该在this等于Form的地方运行。或者如果你更喜欢在其他地方运行它,那么你需要将Form作为参数传递给那个方法,并在那里调用Suspend...+Resume...。

chhkpiq4

chhkpiq42#

对于像ListViewDataGridView这样承载大量项目的控件,提高性能的一种方法是使用VirtualMode=true将底层列表项目的更改与UI绘制解耦。由此推论,如果您想要编写一个函数来获取需要检查的项目列表,则根本不需要接触UI,并且应该很快。

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        for (int i = 1; i <= 3000; i++)
        {
            SecuritiesList.Add(new Security { Text = $"Security {i}", IsChecked = false });
        }
        m_lsvSecurities.View = View.Details;
        m_lsvSecurities.HeaderStyle = ColumnHeaderStyle.None;
        m_lsvSecurities.Columns.Add("", 80);
        m_lsvSecurities.Columns.Add("Security", 300);
        m_lsvSecurities.CheckBoxes = true;
        m_lsvSecurities.VirtualMode = true;
        m_lsvSecurities.RetrieveVirtualItem += (sender, e) =>
        {
            if (e.ItemIndex >= 0 && e.ItemIndex < SecuritiesList.Count)
            {
                var security = SecuritiesList[e.ItemIndex];
                ListViewItem item = new ListViewItem(text: security.IsChecked ? "\u2612" : "\u2610");
                item.SubItems.Add(security.Text);
                e.Item = item;
            }
            else
            {
                e.Item = new ListViewItem();
            }
        };
        m_lsvSecurities.MouseClick += (sender, e) =>
        {
            var hti = m_lsvSecurities.HitTest(e.Location);
            if (hti.Location == ListViewHitTestLocations.Label)
            {
                var security = SecuritiesList[hti.Item.Index];
                security.IsChecked = !security.IsChecked;
                m_lsvSecurities.Invalidate(hti.Item.Bounds);
            }
        };
        m_lsvSecurities.VirtualListSize = SecuritiesList.Count;
        _ = benchmark();
    }
    private List<Security> SecuritiesList { get; } = new List<Security>();
}

字符串
生成3000个证券的列表并显示该列表后,2秒后调用benchmark()方法来测量获取需要检查的项目列表所需的时间,在本例中是“每四个项目”。


的数据

/// <summary>
    ///  Show the dialog, wait 2 seconds, then 
    ///  run conditional set check for 3000 items.
    /// </summary>
    async Task benchmark()
    {
        await Task.Delay(TimeSpan.FromSeconds(2));
        Text = DateTime.Now.ToString(@"hh\:mm\:ss\.ffff tt");
        screenshot("screenshot.1.png");
        var stopwatch = Stopwatch.StartNew();

        // Example of a function that will get list
        // of items that need to be checked.
        setListOfItemsConditionalChecked();

        m_lsvSecurities.Refresh();
        stopwatch.Stop();
        Text = DateTime.Now.ToString(@"hh\:mm\:ss\.ffff tt");
        await Task.Delay(TimeSpan.FromSeconds(0.5));
        MessageBox.Show($"{stopwatch.ElapsedMilliseconds} ms");
    }

    private void setListOfItemsConditionalChecked()
    {
        for (int i = 0; i < SecuritiesList.Count; i++) 
        {
            var mod = i + 1;
            SecuritiesList[i].IsChecked = (mod % 4 == 0);
        }
    }

列表项类

{
    public string Text { get; set; }
    public bool IsChecked { get; set; }
}

相关问题