How to update ListView's selected item?

c#, listview, winforms

Solution

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.

Problem

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?

Original source