I have an event set up to fire when an item in a ListView is checked. The event calls a function which updates various controls inside my form. Among other things, I need to enable or disable buttons based on how many items are checked. This function is quite expensive.
Example:
private void listView_ItemCheck(object sender, ItemCheckEventArgs e)
{
    UpdateForm();
}
Now the problem arises when a user wants to check many items at once. This causes the application to be unresponsive for a little while.
So, I would like to call UpdateForm() once after all the items were checked, instead of every time a single item is checked.
EDIT:
Here's a part of UpdateForm():
private void UpdateForm()
{
    // Puts all files in the mod list in a new list
    List<string> modListFiles = new List<string>(lvFiles.Items.Count);
    foreach (ListViewItem lvi in lvFiles.Items)
    {
        modListFiles.Add(lvi.Text);
    }
    // Adds found files to the file list
    foreach (string file in Files)
    {
         lvFiles.Items.Add(new ListViewItem(file));
    }
    // Removes files from mod list that no longer exist
    List<string> deleteQue = new List<string>(lvFiles.Items.Count);
    foreach (string file in modListFiles)
    {
        // If a file in the list doesn't exist anymore, que it to delete
        if (!Files.Contains(file))
        {
            deleteQue.Add(file);
        }
    }
    // Remove queued files
    foreach (string file in deleteQue)
    {
        foreach (ListViewItem lvi in lvFiles.Items)
        {
            if (lvi.Text == file)
            {
                lvFiles.Items.Remove(lvi);
                break;
            }
        }
    }
    // Grays out mod list if a profile is installed
    if (InstalledProfile == null)
    {
        lvFiles.BackColor = SystemColors.Window;
        lvFiles.ForeColor = SystemColors.WindowText;
    }
    else
    {
        lvFiles.BackColor = SystemColors.Control;
        lvFiles.ForeColor = SystemColors.ControlDark;
    }
    // Fills out the game path if it exists
    if (Directory.Exists(GamePath))
    {
        txtGamePath.Text = GamePath;
    }
    else
    {
        txtGamePath.Text = "Game directory does not exist!";
    }
    // Makes sure that the cbxProfiles_SelectedIndexChanged doesn't run UpdateForm() again
    handleProfileChanged = false;
    // Adds profiles to the combobox
    foreach (string profile in Profiles)
        {
        if (!cbxProfiles.Items.Contains(profile))
        {
            cbxProfiles.Items.Add(profile);
        }
    }
    // Removes nonexistant profiles from the combobox
    foreach (string profile in cbxProfiles.Items)
    {
        if (!Profiles.Contains(profile))
        {
            cbxProfiles.Items.Remove(profile);
        }
    }
    if (InstalledProfile == null)
    {
        btnInstallUninstall.Text = "Install";
    }
    else
    {
        btnInstallUninstall.Text = "Uninstall";
    }
    if (Directory.Exists(GamePath) && lvFiles.CheckedItems.Count > 0)
    {
        btnInstallUninstall.Enabled = true;
    }
    else
    {
        btnInstallUninstall.Enabled = false;
    }
}
I've had to simplify some things so please excuse any errors I have probably made.
Some context:
I'm trying to make a program that copies files from a set directory \mods to a user specified directory GamePath. It shows all files found in \mods, then allows the user to check some of them. Clicking btnInstall will copy these files to GamePath. After this so called installing, the copied files can be removed by clicking btnInstall again.
All of the properties I made (Profiles, GamePath) get and set their values using an XML file on disk. The main ListView is called lvFiles, sometimes called mod list or file list in comments.
