XstreamINsanity XstreamINsanity - 6 months ago 28
C# Question

How do I edit the name of an item in a CheckedListBox?

I have a

CheckedListBox
that has X number of items. These items are placed there at runtime. These items are supposed to represent reports that can be displayed in the
DataGridView
. What I need to do now is display the record count for each report in parenthesis right next to the report name. I tried, not for too long, to edit the actual name of the item but couldn't find out how to do it. So then, I brute forced it. Saved the items to an array, cleared the items, appended the record counts to each item in the array, created new items. Well, this has caused issues because now it's not retaining my checks and the reason why is because whenever I generate the reports, I clear the items and recreate them. Well, rather than doing another
foreach
loop to save the checked status, does anyone know of a way to change the text of existing items in a
CheckedListBox
?

Here is the code I currently have:

In the MainForm.Designer.cs:

this.clbReports.Items.AddRange(new object[] {
"Report 1",
"Report 2",
"Report 3",
"Report 4",
"Report 5",
"Report 6",
"Report 7",
"Report 8",
"Report 9",
"Report 10",
"Report 11"});


And it looks like:

alt text

And I want it to look like (but there won't all be 0's):

alt text

Here is the SelectedIndexChanged function:

private void clbReports_SelectedIndexChanged(object sender, EventArgs e)
{
string strCheckBox = clbReports.SelectedItem.ToString();
bool bShowAllIsChecked = clbReports.GetItemChecked(clbReports.FindString("Show All Error Reports"));
bool bSelected = clbReports.GetItemChecked(clbReports.FindString(strCheckBox));
int nIndex = -1;

if (strCheckBox.Contains("Show All Error Reports"))
{
foreach (string str in _strReports)
{
if (!str.Contains("Show All Error Reports") && !str.Contains("Show Tagged Records"))
{
nIndex = clbReports.FindString(str);
if (nIndex > -1)
{
clbReports.SetItemChecked(nIndex, bSelected);
}
}
}
}
else
{
if (strCheckBox.Contains("Show All Error Reports") || bShowAllIsChecked)
{
foreach (string str in _strReports)
{
nIndex = clbReports.FindString(str);
if (nIndex > -1)
{
clbReports.SetItemChecked(nIndex, false);
}
}
}

nIndex = clbReports.FindString(strCheckBox);
if (nIndex > -1)
{
clbReports.SetItemChecked(nIndex, bShowAllIsChecked ? true : bSelected);
}
}

string[] strCheckedItems = new string[clbReports.CheckedItems.Count];
clbReports.CheckedItems.CopyTo(strCheckedItems, 0);
List<string> checkBoxReportFilter = new List<string>();
foreach (ReportRecord obj in this._lstReportRecords)
{
foreach (string str in strCheckedItems)
{
if (str.Contains(obj.Description))
{
checkBoxReportFilter.Add(obj.PartID.ToString());
}
}
}
try
{
if (checkBoxReportFilter.Count == 0 && clbReports.CheckedItems.Count > 0)
{
throw new NullReferenceException();
}

_strReportFilter = String.Join(",", checkBoxReportFilter.ToArray());
}
catch (NullReferenceException)
{
_strReportFilter = "-1";
}

generateReport();
}


And here is the code where I am clearing the items, getting the report counts and creating the new items.

_lstReportRecords = _dataController.ReportList;
bool[] bChecked = new bool[clbReports.Items.Count];
int nCounter = 0;
foreach (string str in _strReports)
{
foreach (string str2 in clbReports.SelectedItems)
{
bChecked[nCounter] = str2.Contains(str);
}
nCounter++;
}

clbReports.Items.Clear();
nCounter = 0;

foreach (string str in _strReports)
{
int nCount = _lstReportRecords.Where<ReportRecord>(delegate(ReportRecord rr) {
return rr.Description == str;
}).Count();

string newReport = str + " (" + nCount + ")";
clbReports.Items.Add(newReport);
clbReports.SetItemChecked(nCounter, bChecked[nCounter]);
nCounter++;
}


Please tell me there is an easier way to do this. I tried doing foreach loops through the clbReports.Items but it wants me to cast it to a string (errored on me when trying to cast to a CheckBox) so I couldn't change the value. And even if I could cast it to a CheckBox, I have a feeling it will give me the error that Enumeration has failed because the list has been changed (or however they word it). Any and all help is welcome. Thanks.

Edit: Please know that the Report X are just so that the actual report names aren't displayed to keep it generic. However, in the code, I just copied and pasted so the Show All Error Reports and Show All Tagged Records are reports I need to check.

Answer Source

Well, due to time constraints I tried something else. I went with a ListView where CheckBoxes = true and View = List. I also removed Show All Error Reports and Show Tagged Records to checkboxes outside of the list. This made it a lot easier to do the functions I wanted. Here is the new code.

MainForm.Designer.cs

    // 
    // cbTaggedRecords
    // 
    this.cbTaggedRecords.AutoSize = true;
    this.cbTaggedRecords.Location = new System.Drawing.Point(151, 9);
    this.cbTaggedRecords.Name = "cbTaggedRecords";
    this.cbTaggedRecords.Size = new System.Drawing.Size(106, 17);
    this.cbTaggedRecords.TabIndex = 3;
    this.cbTaggedRecords.Text = "Tagged Records";
    this.cbTaggedRecords.UseVisualStyleBackColor = true;
    this.cbTaggedRecords.CheckedChanged += new System.EventHandler(this.ShowTaggedRecords_CheckChanged);
    // 
    // cbAllErrorReports
    // 
    this.cbAllErrorReports.AutoSize = true;
    this.cbAllErrorReports.Location = new System.Drawing.Point(6, 9);
    this.cbAllErrorReports.Name = "cbAllErrorReports";
    this.cbAllErrorReports.Size = new System.Drawing.Size(102, 17);
    this.cbAllErrorReports.TabIndex = 2;
    this.cbAllErrorReports.Text = "All Error Reports";
    this.cbAllErrorReports.UseVisualStyleBackColor = true;
    this.cbAllErrorReports.CheckedChanged += new System.EventHandler(this.ShowAllErrorReports_CheckChanged);
    // 
    // listView1
    // 
    this.listView1.CheckBoxes = true;
    listViewItem1.StateImageIndex = 0;
    listViewItem2.StateImageIndex = 0;
    listViewItem3.StateImageIndex = 0;
    listViewItem4.StateImageIndex = 0;
    listViewItem5.StateImageIndex = 0;
    listViewItem6.StateImageIndex = 0;
    listViewItem7.StateImageIndex = 0;
    listViewItem8.StateImageIndex = 0;
    listViewItem9.StateImageIndex = 0;
    this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
    listViewItem1,
    listViewItem2,
    listViewItem3,
    listViewItem4,
    listViewItem5,
    listViewItem6,
    listViewItem7,
    listViewItem8,
    listViewItem9});
    this.listView1.Location = new System.Drawing.Point(6, 29);
    this.listView1.Name = "listView1";
    this.listView1.Size = new System.Drawing.Size(281, 295);
    this.listView1.TabIndex = 1;
    this.listView1.UseCompatibleStateImageBehavior = false;
    this.listView1.View = System.Windows.Forms.View.List;
    this.listView1.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.listView_ItemChecked);

MainForm.cs

    private void listView_ItemChecked(object sender, ItemCheckedEventArgs e)
    {
        if (e != null)
        {
            int nLength = e.Item.Text.IndexOf("(") - 1;
            string strReport = nLength <= 0 ? e.Item.Text : e.Item.Text.Substring(0, nLength);
            if (e.Item.Checked)
            {
                _lstReportFilter.Add(strReport);
            }
            else
            {
                _lstReportFilter.Remove(strReport);
            }
        }

        List<string> checkBoxReportFilter = new List<string>();
        foreach (ReportRecord obj in this._lstReportRecords)
        {
            foreach (string str in _lstReportFilter)
            {
                if (str.ToLower().Contains(obj.Description.ToLower()))
                {
                    checkBoxReportFilter.Add(obj.PartID.ToString());
                }
            }
        }
        try
        {
            if (checkBoxReportFilter.Count == 0 && listView1.CheckedItems.Count > 0)
            {
                throw new NullReferenceException();
            }

            _strReportFilter = String.Join(",", checkBoxReportFilter.ToArray());
        }
        catch (NullReferenceException)
        {
            _strReportFilter = "-1";
        }

        if (!bShowAll)
        {
            generateReport();
        }
    }

    private void ShowAllErrorReports_CheckChanged(object sender, EventArgs e)
    {
        bShowAll = true;
        foreach (ListViewItem lvi in listView1.Items)
        {
            lvi.Checked = ((CheckBox)sender).Checked;
        }

        _lstReportFilter.Clear();
        bShowAll = false;
        generateReport();
    }

    private void ShowTaggedRecords_CheckChanged(object sender, EventArgs e)
    {
        bool bChecked = ((CheckBox)sender).Checked;
        if (bChecked)
        {
            if (!_lstReportFilter.Contains("Show Tagged Records"))
            {
                _lstReportFilter.Add("Show Tagged Records");
            }
        }
        else
        {
            _lstReportFilter.Remove("Show Tagged Records");
        }

        listView_ItemChecked(null, null);
    }

Code to add counts to CheckBoxes

            _lstReportRecords = _dataController.ReportList;

            int nTotalCount = 0;

            foreach (ListViewItem lvi in listView1.Items)
            {
                int nCount = _lstReportRecords.Where(rr => lvi.Text.Contains(rr.Description)).Count();
                nTotalCount += nCount;
                lvi.Text = (lvi.Text.Contains("(") ? lvi.Text.Substring(0, lvi.Text.IndexOf("(") + 1) : lvi.Text + " (") + nCount.ToString() + ")";
            }

            cbAllErrorReports.Text = (cbAllErrorReports.Text.Contains("(") ? cbAllErrorReports.Text.Substring(0, cbAllErrorReports.Text.IndexOf("(") + 1) : cbAllErrorReports.Text + " (") + nTotalCount.ToString() + ")";
            int nTaggedCount = _lstReportRecords.Where(rr => rr.Description.Contains("Tagged")).Count();
            cbTaggedRecords.Text = (cbTaggedRecords.Text.Contains("(") ? cbTaggedRecords.Text.Substring(0, cbTaggedRecords.Text.IndexOf("(") + 1) : cbTaggedRecords.Text + " (") + nTaggedCount.ToString() + ")";

Thank you all for your help and ideas.