2010-09-08 108 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" 

是的,那些項目類型的「對象」。不,沒人知道,字符串也是一個對象;)

相關問題