2010-09-08 58 views
1

我有一个CheckedListBox有X个项目。这些项目在运行时放置在那里。这些项目应该代表可以在DataGridView中显示的报告。我现在需要做的是在报告名称旁边的括号内显示每个报告的记录计数。我试了一下,并没有太长时间来编辑项目的实际名称,但无法知道如何去做。那么,我蛮横的强迫它。将项目保存到数组中,清除项目,将记录计数附加到数组中的每个项目,创建新项目。那么,这已经造成了问题,因为现在它不保留我的支票,原因是因为每当我生成报告时,我都清除这些项目并重新创建它们。那么,有没有人知道更改CheckedListBox中现有项目的文本的方法,而不是做另一个foreach循环来保存检查的状态?如何编辑CheckedListBox中的项目名称?

这里是我目前拥有的代码:

在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"}); 

它看起来像:

alt text

而且我希望它看起来像(但不会全都是0):

alt text

这里是的SelectedIndexChanged功能:

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(); 
} 

而这里就是我清理的项目,得到了报告数量和创造新项目的代码。

_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++; 
} 

请告诉我,还有一个更简单的方法来做到这一点。我尝试了通过clbReports.Items做foreach循环,但它想让我把它转换为一个字符串(当试图转换为CheckBox时出错),所以我无法更改该值。即使我可以将它转换为CheckBox,我也有一种感觉,它会给我Enumeration失败的错误,因为列表已被更改(或者他们用它来表示)。任何和所有的帮助是受欢迎的。谢谢。

编辑:请知道,报告X只是为了使实际的报告名称不显示为通用。但是,在代码中,我只是复制并粘贴,以便显示所有错误报告和显示所有标记记录是我需要检查的报告。

+0

你不需要在clbReports_SelectedIndexChanged的else语句中如果strCheckBox.Contains(“显示所有错误报告”),因为它永远不会是真的,因为它们都将进入'如果'部分,从来没有其他人。只是一点点,但它会帮助保持代码更清晰 – w69rdy 2010-09-08 13:31:05

+0

为什么不只是'int nCount = _lstReportRecords.Where(rr => rr.Description == str)'而不是复杂的方式? – Timwi 2010-09-08 13:33:04

+0

@Timwi - 老实说,因为我不知道这是一个更简单的方法。 :)我认为你必须做类似于你定义一个函数的JavaScript。现在在我的代码中改变了....在我所做的所有地方都是这样。 :) – XstreamINsanity 2010-09-08 13:35:55

回答

0

那么,由于时间限制,我尝试了别的东西。我去了一个ListView,其中CheckBoxes = true和View = List。我还删除了显示所有错误报告并显示标记记录到列表外的复选框。这使得执行我想要的功能变得更容易。这是新的代码。

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); 
    } 

代码以计数增加的CheckBox

  _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() + ")"; 

感谢大家的帮助和想法。

1

如果我是你,我会尝试给INotifyPropertyChanged接口一个去。 除非必要,否则不应该混淆事件。这将意味着你不能使用设计器创建的项目,但据我了解,这是一个运行时修改的列表反正...

详细:

•创建一个类(例如'福')实现INotifyPropertyChanged(基本上这会告诉任何听众文本属性已更改)。该课程将保存所有条目的名称。

•创建ObservableCollection并将CheckedListBox绑定到该集合。在WinForms中,您将不得不创建一个DataBindingSource并将您的Collection插入到一端,并将ComboBox插入到另一端。

•对控件的任何更改都会显示在控件中。

HTH 塞比

+0

感谢您的建议,但这可能比现在需要的多一点。我在网上查看其他示例,我想我可能只是使用带有CheckBoxes = true和View = List的ListView。我不知道为什么以前的程序员想要使用CheckedListBox,看起来似乎非常有限。不过谢谢。 – XstreamINsanity 2010-09-08 13:46:51

0

为了改变在ListBox中的项目(或CheckedListBox),你应该改变这些项目ToString()结果。

最简单的解决方案是创建一个“Holder”类,该类引用了它所代表的报告。然后该样品架类的ToString()方法应该是这样的:

public override string ToString() 
{ 
    return String.Format("{0} ({1})", BaseStr, MyReport.RecordCount); 
} 

如果更改MyReport.RecordCount莫名其妙(因为报表的记录数的变化),你可以叫clbReports.Refresh(),它会自动显示新值。

我想这样你甚至不需要第二个代码块中的临时数组解决方案;不过,我想建议一种获得物品检查状态的替代方法。 您可以循环访问clbReports.CheckedIndices,并且只为该数组中的索引填充bChecked数组的值true

1

权(==最简单,最直接的)的答案和解决方案是:

this.clbReports.Items[nIndex] = "new text of the item" 

是的,那些项目类型的“对象”。不,没人知道,字符串也是一个对象;)

相关问题