2010-09-08 3 views
1

У меня есть CheckedListBox, который имеет X количество элементов. Эти элементы размещаются там во время выполнения. Эти элементы должны представлять отчеты, которые могут отображаться в DataGridView. Теперь мне нужно показать количество записей для каждого отчета в скобках рядом с именем отчета. Я пытался, не слишком долго, редактировать фактическое имя элемента, но не смог узнать, как это сделать. Итак, я переборщил. Сохраняли элементы в массиве, очищали элементы, добавляли количество записей к каждому элементу массива, создавали новые элементы. Ну, это вызвало проблемы, потому что теперь оно не удерживает мои чеки, и причина в том, что всякий раз, когда я создаю отчеты, я очищаю их и воссоздаю. Ну, вместо того, чтобы делать еще один цикл foreach, чтобы сохранить проверенный статус, знает ли кто-нибудь об изменении текста существующих элементов в CheckedListBox?Как изменить имя элемента в 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++; 
} 

Скажите, пожалуйста, что есть более простой способ сделать это. Я пробовал делать петли foreach через clbReports.Items, но он хочет, чтобы я применил его к строке (с ошибкой при попытке применить к CheckBox), поэтому я не мог изменить значение. И даже если бы я мог передать его в CheckBox, у меня возникло ощущение, что он даст мне ошибку, которую перечислил, потому что список был изменен (или, как бы то ни было, они его называют). Любая помощь приветствуется. Благодарю.

Редактировать: Пожалуйста, имейте в виду, что отчет X предназначен только для того, чтобы фактические имена отчетов не отображались, чтобы сохранить их общий. Однако в коде я просто скопировал и вставил, чтобы показать все отчеты об ошибках и показать все отмеченные записи - отчеты, которые мне нужно проверить.

+0

Вам не нужно, если strCheckBox.Contains («Показать все отчеты об ошибках») в инструкции else из clbReports_SelectedIndexChanged, потому что это никогда не будет правдой, поскольку все они войдут в раздел «если», а не другое. Просто немного, но это поможет сохранить код более четким. – w69rdy

+0

Почему не просто 'int nCount = _lstReportRecords.Where (rr => rr.Description == str)' вместо запутанного пути? – Timwi

+0

@ Тимви - Честно говоря, потому что я не знал, что это был более простой способ. :) Я думал, что вам нужно сделать это подобно javascript, где вы определяете функцию. Это теперь изменяется в моем коде .... во ВСЕХ местах, где я так делал. :) – XstreamINsanity

ответ

0

Ну, из-за ограничений по времени я попробовал что-то еще. Я пошел с ListView, где CheckBoxes = true и View = List. Я также удалил Show All Error Reports и Show Tagged Records для флажков вне списка. Это значительно облегчило выполнение функций, которые я хотел. Вот новый код.

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

код для добавления счетчиков в 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() + ")"; 

Спасибо всем за помощь и идеи.

1

Если бы я был вами, я попытался бы дать интерфейсу INotifyPropertyChanged. Вы не должны вмешиваться в события, если это необходимо. это будет означать, что вы не можете использовать конструктор для создания элементов, но, насколько я понял, это исполняемый модифицированный список в любом случае ...

Подробно:

• Создать класс (eg'Foo '), который реализует INotifyPropertyChanged (в основном это скажет любому слушателю, что свойство text изменилось). Этот класс будет содержать имена всех записей.

• создайте ObservableCollection и привяжите свой CheckedListBox к этой коллекции. В WinForms вам нужно будет создать источник DataBindingSource и подключить свою коллекцию к одному концу, а ComboBox - к другому концу.

• Любые изменения, внесенные в коллекцию, будут видны в элементе управления.

НТН Sebi

+0

Спасибо за предложение, но это может быть немного больше, чем нужно прямо сейчас. Я просматриваю другие примеры в Интернете, и я думаю, что могу просто использовать ListView с CheckBoxes = true и View = List. Я не знаю, почему предыдущий программист хотел использовать CheckedListBox, видя, как он выглядит очень ограниченным. Спасибо хоть. – XstreamINsanity

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" 

да, эти элементы типа «объект». Нет, никто не возражает, что строка тоже является объектом;)

Смежные вопросы