I have a TextBox that searches whatever I have in my ListView. I would like to have a ComboBox that will allow the user to “Show All”, “Show Match” and “Show Non Match” within the ListView depending on search criteria.
private void SearchBtn_Click(object sender, EventArgs e)
{
int count = 0, searchStartIndex = selectedIndexPos = 0;
// Clear previously selected indices
listView.SelectedIndices.Clear();
string target = searchTextBox.Text;
// Search for item with text from the search text box, including subItems, from searchStartIndex, not a prefixSearch
ListViewItem item = listView.FindItemWithText(target, true, searchStartIndex, false);
/*----------------------------------------------------------------------------------------------------*
* While the search results in an item found continue searching. *
*----------------------------------------------------------------------------------------------------*/
while (item != null)
{
count++;
// Update progressBar
progressBar.Value = (int)((float)searchStartIndex / listView.VirtualListSize * 100);
ListView.SelectedIndexCollection indexes = listView.SelectedIndices;
if (!indexes.Contains(item.Index))
{
listView.SelectedIndices.Add(item.Index);
}
/*----------------------------------------------------------------------------------------------------*
* Set the start index to the index after the last found, if valid start index search for next item.*
*----------------------------------------------------------------------------------------------------*/
if ((searchStartIndex = item.Index + 1) < listView.VirtualListSize)
{
item = listView.FindItemWithText(searchTextBox.Text, true, searchStartIndex, false);
// count++;
}
else
{
item = null;
}
}
if (listView.SelectedIndices.Count == 0)
{
MessageBox.Show("Find item with text \"" + searchTextBox.Text + "\" has no result.");
}
else
{
RefilterListView();
listView.EnsureVisible(listView.SelectedIndices[0]);
}
}
I would like to have my items in the 'ComboBox' to help filter my 'ListView'. The "Show All" should display all contents of 'ListView' along with item that was searched, the "Show Match" should show only the searched item removing everything else that doesn't match the search and "Show Non Match" should show all of the contents from 'ListView' that doesn't match the searched item.
I can't do it exactly in your case. But I hope I realize it. I mean this is just a solution. You can customize it for your case.
First of all, put a BindingSource on your Form and bind it to your data:
bindingSource1.DataSource = data;
Then bind your ListView(actually DataGridView) to the BindingSource:
dataGridView1.DataSource = bindingSource1;
And then define an enum like this:
public enum Something
{
ShowMatch = 1,
ShowNonMatch = 2
}
Now, put a ComboBox on your Form and add your options to it:
comboBox1.Items.Add("Show All");
comboBox1.Items.Add("ShowMatch");
comboBox1.Items.Add("ShowNonMatch");
comboBox1.SelectedIndex = 0;
After that, you can catch the selected item in SelectedIndexChanged:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
bindingSource1.Filter = null;
else
bindingSource1.Filter = $"Name = '{comboBox1.SelectedItem.ToString()}'";
}
Using C# and forms. I have a datagridview which has two of the three fields visible in the table which is editable and addable. The third field is in a combobox.
When updating the database (hitting enter after adding in the empty row) I get an error saying that the third field can't be null. I'd like to have the value in the combobox be used for the third field.
I can't seem to figure it out. Should I be using an event, somehow?
private void cmbMCID_SelectedIndexChanged(object sender, EventArgs e)
{
var cMarks = (from cm in DB.Student_Courses
where cm.CID == Convert.ToInt32(cmbMCID.Text)
select cm).ToList();
Student_Course sc = new Student_Course();
//cMarks.Add(sc);
studentCourseBindingSource.DataSource = cMarks;
sc.CID = Convert.ToInt32(cmbMCID.Text);
//studentCourseBindingSource.ResetBindings(false);
}
I've attempted to added a RowsAdded Event but didn't come out on top.
private void dgvSMarks_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
if (tabControl1.SelectedIndex == 3)
{
Student_Course sc = new Student_Course();
sc.CID = Convert.ToInt32(cmbMCID.Text);
}
}
Great, OK. so I was doing horrible things - with the combobox. A mix of needing to making a selection in the combobox first (otherwise returned null) and trying to commit what was already in the database.
Needed to create a for loop through the dgv collection, too.
private void dgvSMarks_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
// if (dgvSMarks.ContainsFocus == true)
// {
// // Get the RowIndex of the CID Cell, and add the combobox MCID value to it
// dgvSMarks.Rows[e.RowIndex-1].Cells[0].Value = Convert.ToInt32(cmbMCID.Text);
// }
var student_course = new Student_Course();
var course = new Course();
//MessageBox.Show("Row Count is " + dgvSMarks.Rows.Count);
for (int i = 1; i < dgvSMarks.Rows.Count; i++)
{
if (i == (dgvSMarks.Rows.Count - 1))
{
student_course.CID = Convert.ToInt32(cmbMCID.Text);
student_course.SID = Convert.ToInt32(dgvSMarks.Rows[i - 1].Cells[1].Value);
student_course.Mark = Convert.ToInt32(dgvSMarks.Rows[i - 1].Cells[2].Value);
DB.Student_Courses.InsertOnSubmit(student_course);
DB.SubmitChanges();
}
}
}
Thanks to the help of my CPI instructors. :)
I am making an web application for articles reading.
I have bool property which is set to true if the specific Edit Button is clicked, there is also a Save Button which is clicked after filling user information on TextBoxes and other controls. Whenever I run my application and fills information, it runs fine but after 4 or 5 runs (re-starting the application) it gives an Exception error upon clicking Save Button:
Input string was not in a correct format which is due to filling TextBoxes with Null( firstly, Null is converted into Int).
My problem is that bool property (Managment.IsEditing) is set to true without any reason ( Edit Button should be pressed to set bool to true). Why and how is set to true automatically as its code is only being called in EditButton_Click Event?
Here is a code
protected void EditButton_Click(object sender, EventArgs e)
{
if(EditorList.SelectedIndex > -1) //Just to ensure that Item is selected from ListBox
{
//editor is the poco , EditorManager is the editor table manager
editor = EditorManager.GetEditorInfo(EditorList.SelectedValue);
NameTextBox.Text = editor.Name;
EmailTextBox1.Text = editor.Email;
PasswordTextBox.Text = editor.Password;
EditorIDTextBox.Text = editor.Editor_ID.ToString();
for (int index = 0; index < RoleCheckBoxList.Items.Count; index++)
{
RoleCheckBoxList.Items[index].Selected = editor.RoleList[index];
}
Managment.IsEditing = true; //This flag is responsible for telling "SaveButtton" that editor would be updated.
DeleteButton.Enabled = true;
ResultLabel.Text = "";
}
else
ResultLabel.Text = "Select Editor from list first";
protected void SaveButton_Click(object sender, EventArgs e)
{
if(Managment.IsEditing == false) //it makes sure that new editor is being saved
{
editor.Name = NameTextBox.Text;
string email = EmailTextBox1.Text;
editor.Email = email.ToLower();
editor.Password = PasswordTextBox.Text;
if(EditorManager.IsEditorValid(editor.Email))
{
for (int index = 0; index < RoleCheckBoxList.Items.Count; index++)
{
editor.RoleList[index] = RoleCheckBoxList.Items[index].Selected;
}
EditorManager.Save(editor);
ResultLabel.Text = editor.DataUploadMessage;
}
else
ResultLabel.Text = "Editor with the same Email can't be add!";
FillEditorList();
}
else if(Managment.IsEditing == true) //it determines that existing editor is being updated and problem is that Managment.IsEditing is turned on without being called.
{
editor.Name = NameTextBox.Text;
string email = EmailTextBox1.Text;
editor.Email = email.ToLower();
editor.Password = PasswordTextBox.Text;
editor.Editor_ID = Convert.ToInt32(EditorIDTextBox.Text);// Error occurs at this line
for (int index = 0; index < RoleCheckBoxList.Items.Count; index++)
{
editor.RoleList[index] = RoleCheckBoxList.Items[index].Selected;
}
EditorManager.Edit(editor);
ResultLabel.Text = editor.DataUploadMessage;
Managment.IsEditing = false;
FillEditorList();
}
ClearFields(Form.Controls);
}
Exception occurs on that line:
editor.Editor_ID = Convert.ToInt32(EditorIDTextBox.Text);
and sorry for any inconvenience dear fellows
When the exception occurs on the indicated line, the line that resets your flag won't be run. The page will then likely be in an invalid state.
Try fixing/handling the error and clean up properly, and the problem might go away.
I have a DataGridView where I am scanning in checks from a keyboard emulated device.
While keypreview is on and I'm waiting for input, the user cannot type anything in otherwise it grabbed by my method to read the input by the check reader. All this is working fine.
After the scan, I am adding to the datagridview a row, which is being put at the end.
How do I make the datagridview scroll to the bottom after each add? I wind up with a few hundred checks and it's at the top. So, every time they scan, they have no idea what was scanned in.
This is my method that creates the row:
private void Timer1Tick(object sender, EventArgs e)
{
_secondswaited += 1;
if (_secondswaited == SecondsToWait)
{
timer1.Enabled = false;
var psc = new ParseScannedCheckNumbers();
if (psc.ParseCheck(_checkData))
{
label_Status.Text = #"Scan Next Check";
var ct = checkTrans.IndividualCheck.NewIndividualCheckRow();
ct.Date = DateTime.Now.ToShortDateString();
ct.AccountNumber = GetAccountNumber(psc.BankAccountNumber);
ct.Name = GetAccountName(ct.AccountNumber);
ct.AccountBalance = GetAccountBalance(ct.AccountNumber);
//ct.CheckAmount = 0;
ct.BankRoutingNumber = psc.BankRoutingNumber;
ct.BankAccountNumber = psc.BankAccountNumber;
ct.CheckNumber = psc.CheckNumber;
ct.Status = "Entered";
checkTrans.IndividualCheck.Rows.Add(ct);
var dgvcount = dgv_Checks.Rows.Count;
**dgv_Checks.Rows[dgvcount - 1].Selected = true;**
}
else
{
label_Status.Text = #"Scan failed. Rescan check.";
}
_checkData = string.Empty;
_secondswaited = 0;
var rs = new Registry.RegistrySettings();
if (!rs.ScanChecksContinuous)
{
StopScanning();
label_Status.Text = #"Success!";
EditLastRowEntered();
}
label_ChecksScanned.Text = (dgv_Checks.RowCount - 1).ToString();
}
}
The part that is bold is where I attempted to move to the last row, without success.
Thanks!
I'd use the DataGridView.CurrentCell property. Try this in place of the line you're having problems with:
dgv_Checks.CurrentCell = dgv_Checks.Rows[dgvcount - 1].Cells[0];
What i think you need to do is check to see if the Row is being displayed.
and then
replace the line in bold with
if(dgv_Checks.Rows[dgvcount - 1].Displayed == false)
{
dgv_Checks.FirstDisplayedScrollingRowIndex = dgvcount - 1;
}
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:
And I want it to look like (but there won't all be 0's):
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.
The right ( == most simple and most direct) answer and solution is:
this.clbReports.Items[nIndex] = "new text of the item"
yes, those items are of type "object". No, nobody minds that, string is an object too ;)
If I were you, I'd try to give the INotifyPropertyChanged Interface a go.
You Shouldn't mess with events unless necessary. this will mean you can't use the designer to create the items, but as far as I've understood, it's a runtime-modified list anyway...
In detail:
• Create A Class (e.g.'Foo') that Implements INotifyPropertyChanged (Basically this will tell any listener that the text property has changed). This class will hold the names of all entries.
• create an ObservableCollection and bind your CheckedListBox to that Collection. In WinForms you will have to create a DataBindingSource and plug your Collection to one end and the ComboBox to the other end.
• Any change made to the collection will be visible in the control.
HTH
Sebi
In order to change the items in a ListBox (or a CheckedListBox), you should change these items' ToString() result.
The easiest solution would be to create a "Holder" class, which has a reference to the report it represents. Then the Holder class' ToString() method should be something like this:
public override string ToString()
{
return String.Format("{0} ({1})", BaseStr, MyReport.RecordCount);
}
If you change MyReport.RecordCount somehow (because a report's record count changes), you can just call clbReports.Refresh(), and it'll automatically show the new value.
I think this way you don't even need the temporary array solution in the second code block; however, I'd like to suggest an alternative way of getting the item's checked state.
You can iterate through the clbReports.CheckedIndices, and fill your bChecked array with true values only for indices in that array.
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.