未选中/选中ListViewItem

问题描述 投票:0回答:2

我有一个包含许多项目的 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;
            }
        }
    }
}

oSecurities 有 5 种我想检查的证券。

o物品大小 - 2800 件

为了检查问题,我不得不将函数分成两部分(查找、检查)。

第一部分是一个循环,遍历所有项目,只是使 bFind 为 true 或 false。

当我添加第二部分时

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

它的工作,但太慢了。

当代码执行时 oItem.对 oItems 中的每个 oItem 检查 true 或 false 需要很长时间。

有办法更快地做到这一点吗?

c# winforms listviewitem
2个回答
0
投票

该问题很可能是由组件在每次更新后重新绘制自身引起的。

通常可以通过在进行更改时告诉表单暂停视觉更新来加快速度,如下所示:

this.SuspendLayout();

// Do your updates here

this.ResumeLayout();

它应该运行在

this
等于表单的位置。或者,如果您更喜欢在其他地方运行它,那么您需要将表单作为参数传递给该方法并在那里调用 Suspend...+Resume...。


0
投票

对于像

ListView
DataGridView
这样托管大量项目的控件,提高性能的一种方法是使用
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); // Text column with a width of 200 pixels
        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, then in 2 seconds set the 
    ///  checkboxes to true for 3000 items.
    /// </summary>
    async Task benchmark()
    {
        await Task.Delay(TimeSpan.FromSeconds(2));
        var stopwatch = Stopwatch.StartNew();
        foreach (var item in SecuritiesList)
        {
            item.IsChecked = true;
        }
        m_lsvSecurities.Refresh();
        stopwatch.Stop();
        await Task.Delay(TimeSpan.FromSeconds(0.5));
        MessageBox.Show($"{stopwatch.ElapsedMilliseconds} ms");
    }

地点:

{
    public string Text { get; set; }
    public bool IsChecked { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.