How to update ListView's selected item?

2020-07-16 08:30发布

I have a ListView which displays multiple rows of ListViewItems. The user is able to edit one of these items through a dialog which opens after clicking 'Edit.' When the dialog closes I would like to modify the selected ListViewItem such that it reflects the new settings.

Here is how I currently update my item:

private void btnEditSnmpV3Setting_Click(object sender, EventArgs e)
{
    if (lstVwSNMPv3Settings.SelectedItems.Count > 0)
    {
        ListViewItem selectedItem = lstVwSNMPv3Settings.SelectedItems[0];
        NetworkDiscoverySnmpSetting settings = (NetworkDiscoverySnmpSetting)selectedItem.Tag;
        NetworkDiscoverySnmpV3SettingsDialog dialog = new NetworkDiscoverySnmpV3SettingsDialog(settings);

        //Pass in the owner for centering of dialog.
        if (dialog.ShowDialog(this) == DialogResult.OK)
        {
            selectedItem.SubItems.Clear();
            selectedItem.Text = settings.SnmpV3Username;
            selectedItem.SubItems.Add(settings.SecurityMode.ToString());
            selectedItem.SubItems.Add(settings.AuthenticationProtocol.ToString());
            selectedItem.SubItems.Add(settings.PrivacyProtocol.ToString());
            selectedItem.Tag = settings;
        }
    }
}

I found this to be a poor solution due to the fact that I need to touch code in multiple places if my ListView's number of columns changes.

I handled this code-reuse issue during the 'Add' event (as opposed to 'Edit') by giving NetworkDiscoverySnmpSetting a utility method:

public ListViewItem ToListViewItem()
{
    ListViewItem listViewItem = new ListViewItem();
    listViewItem.Text = SnmpV3Username;
    listViewItem.SubItems.Add(SecurityMode.ToString());
    listViewItem.SubItems.Add(AuthenticationProtocol.ToString());
    listViewItem.SubItems.Add(PrivacyProtocol.ToString());
    listViewItem.Tag = this;
    return listViewItem;
}

which is used like so:

private void btnAddSnmpV3Setting_Click(object sender, EventArgs e)
{
    NetworkDiscoverySnmpSetting settings = new NetworkDiscoverySnmpSetting(NetworkDiscovery.ID);
    NetworkDiscoverySnmpV3SettingsDialog dialog = new NetworkDiscoverySnmpV3SettingsDialog(settings);
    //Pass in the owner for centering of dialog.
    if (dialog.ShowDialog(this) == DialogResult.OK)
        lstVwSNMPv3Settings.Items.Add(settings.ToListViewItem());
}

Unfortunately, ListView.SelectedItems does not allow collection-modification. As such, this does not compile:

lstVwSNMPv3Settings.SelectedItems[0] = settings.ToListViewItem();

How should I change my first code-snippet so that I do not need to update my code in multiple places when ListView's columns change?

3条回答
▲ chillily
2楼-- · 2020-07-16 08:51

A much simpler solution, that worked for me:

lstVwSNMPv3Settings.Items[lstVwSNMPv3Settings.SelectedIndices[0]] = myNewItem;

But be careful to first make sure there is an item selected:

if (lstVwSNMPv3Settings.SelectedIndices.Count > 0) { ... }
查看更多
别忘想泡老子
3楼-- · 2020-07-16 08:55

ListViewItems have a bool Selected property that you can toggle to make them selected or not selected.

查看更多
爷的心禁止访问
4楼-- · 2020-07-16 09:00

You can modify the element itself rather than replacing it with another one, because ListViewItem is a class, so it's a reference type.

In order to do this follow these steps:

  • get currently selected item and save it to variable like this: ListViewItem selectedItem = lstVwSNMPv3Settings.SelectedItems[0];
  • modify your ToListViewItem method to void ToListViewItem(ListViewItem listViewItem) (return void and take ListViewItem object as parameter and modify it instead of creating a new object. It should also rather modify properties of existing subitems than creating new ones. It can look more or less like this:

    public void ToListViewItem(ListViewItem listViewItem)
    {
        listViewItem.Text = SnmpV3Username;
        listViewItem.SubItems[0].Text = SecurityMode.ToString();
        listViewItem.SubItems[1].Text = AuthenticationProtocol.ToString();
        listViewItem.SubItems[2].Text = PrivacyProtocol.ToString();
        listViewItem.Tag = this;
    }
    
  • call ToListViewItem(selectedItem);

  • you don't have to assign the modified item back to the collection, because you use a reference, which means you've just modify the same object that's in the ListView

I did a quick test and the method seems to modify texts of existing items without issues.

查看更多
登录 后发表回答