I am working in a listview where I am trying to add role in it.
I have validation method that prevent the listview to have duplicate role.
The problem is it throws same message twice when I select another list item of listView
and it throws same message thrice when i select the scrollbar of list View. I think
the using the listView.BeginEdit() in wrong way. Please ! help me to sort this problem
Code :
private void AddDefaultRoles()
{
ListViewItem lvi = new ListViewItem("Reader");
listViewRoles.Items.Add(lvi);
lvi = new ListViewItem("Writer");
listViewRoles.Items.Add(lvi);
lvi = new ListViewItem("Administrator");
listViewRoles.Items.Add(lvi);
lvi = new ListViewItem("Delete");
listViewRoles.Items.Add(lvi);
lvi = new ListViewItem("Admin");
listViewRoles.Items.Add(lvi);
lvi = new ListViewItem("Contributor");
listViewRoles.Items.Add(lvi);
lvi = new ListViewItem("Designer");
listViewRoles.Items.Add(lvi);
}
private void button1_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox1.Text))
textBox1.Text = "New Role";
ListViewItem lvi = new ListViewItem(textBox1.Text);
listViewRoles.Items.Add(lvi);
lvi.Selected = true;
lvi.BeginEdit();
}
private void listViewRoles_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
ListViewItem lvi = listViewRoles.Items[e.Item];
string newName = e.Label;
if (newName == null)
newName = lvi.Text;
if (!ValidateRoleName(newName, e.Item))
{
lvi.BeginEdit();
return;
}
}
private void listViewRoles_BeforeLabelEdit(object sender, LabelEditEventArgs e)
{
}
private bool ValidateRoleName(string name, int itemIndex)
{
const bool validName = true;
if ((string.IsNullOrEmpty(name.Trim()))) //empty name
{
MessageBox.Show(this, "empty role name", "Rename failed");
return !validName;
}
if (NameExists(name, itemIndex)) //name already exists
{
MessageBox.Show(this, "already exists", "Rename failed");
return !validName;
}
return validName;
}
private bool NameExists(string newName, int itemIndex)
{
const bool nameExists = true;
for (int i = 0; i < listViewRoles.Items.Count; ++i)
{
if (itemIndex == i)
continue;
if (string.Compare(listViewRoles.Items[i].Text.TrimEnd(), newName.TrimEnd(), true) == 0)
{
return nameExists;
}
}
return !nameExists;
}
Edit (from misplaced answer):
private void listViewRoles_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
ListViewItem lvi = listViewRoles.Items[e.Item];
string newName = e.Label;
if (newName == null)
newName = lvi.Text;
if (_checkRoleName)
{
if (!ValidateRoleName(newName, e.Item))
{
_checkRoleName = false;
lvi.BeginEdit();
return;
}
}
else
{
_checkRoleName = true;
lvi.BeginEdit();
}
}
this.listViewRoles.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.listViewRoles_AfterLabelEdit);
this.listViewRoles.BeforeLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.listViewRoles_BeforeLabelEdit);
When I try the above code it show message box once when i changed the selected index but still when i click the scroll bar, it will called the AfterLabelEdit event so the message called twice. I need a proper solution such that if the added listviewitem is already exists in listview, the added listViewItem persist in edit mode until its name is changed or unique.
You have your call in the wrong event
Use the 'AfterLabelEdit' event.
MSDN AfterLabelEdit
Related
Is there anyway to change the search function for the AutoCompleteStringCollectionclass for the TextBox class? Right now, I have it on the default search function where the beginning letters of my suggestions match the letters of the user input? My suggestions come from a custom source.
You can make your own AutoComplete search - by using TextChange
Here is answer: C# winforms combobox dynamic autocomplete
Code:
string[] data = new string[] {
"Absecon","Abstracta","Abundantia","Academia","Acadiau","Acamas",
"Ackerman","Ackley","Ackworth","Acomita","Aconcagua","Acton","Acushnet",
"Acworth","Ada","Ada","Adair","Adairs","Adair","Adak","Adalberta","Adamkrafft",
"Adams"
};
public Form1()
{
InitializeComponent();
}
private void comboBox1_TextChanged(object sender, EventArgs e)
{
HandleTextChanged();
}
private void HandleTextChanged()
{
var txt = comboBox1.Text;
var list = from d in data
where d.ToUpper().StartsWith(comboBox1.Text.ToUpper())
select d;
if (list.Count() > 0)
{
comboBox1.DataSource = list.ToList();
//comboBox1.SelectedIndex = 0;
var sText = comboBox1.Items[0].ToString();
comboBox1.SelectionStart = txt.Length;
comboBox1.SelectionLength = sText.Length - txt.Length;
comboBox1.DroppedDown = true;
return;
}
else
{
comboBox1.DroppedDown = false;
comboBox1.SelectionStart = txt.Length;
}
}
private void comboBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int sStart = comboBox1.SelectionStart;
if (sStart > 0)
{
sStart--;
if (sStart == 0)
{
comboBox1.Text = "";
}
else
{
comboBox1.Text = comboBox1.Text.Substring(0, sStart);
}
}
e.Handled = true;
}
}
I have an application which loads email-addresses into a list and uses these for autocompletion in a textbox. If I close my application while these addresses are still being retrieved I get the InvalidComObjectException was unhandled by user code error.
The error is specified on a certain piece of code:
Outlook.NameSpace oNS = ((Microsoft.Office.Interop.Outlook.Application)OutlookObj).GetNamespace("MAPI");
This is the entire auto-completion class:
class AutoComplete
{
List<string> emailList = new List<string>();
Outlook.Application OutlookObj = new Outlook.Application();
string[] names;
public List<string> getEmails()
{
Outlook.AddressLists addresslists = OutlookObj.Session.AddressLists;
Outlook.AddressList gal = addresslists["All Users"];
Outlook.AddressEntries addrEntries = gal.AddressEntries;
names = new string[addrEntries.Count];
for (int i = 1; i < addrEntries.Count; i++)
{
Outlook.AddressEntry exchDLMember = addrEntries[i];
Outlook.NameSpace oNS = ((Microsoft.Office.Interop.Outlook.Application)OutlookObj).GetNamespace("MAPI");
Outlook.Recipient recip = oNS.CreateRecipient(exchDLMember.Name);
recip.Resolve();
if (recip.Address != null && recip.AddressEntry != null)
{
if (recip.AddressEntry.GetExchangeUser().PrimarySmtpAddress != null)
{
names[i] = recip.AddressEntry.GetExchangeUser().PrimarySmtpAddress;
}
}
}
foreach (string combo in names)
{
if (combo != null)
{
emailList.Add(combo);
}
else { }
}
return emailList;
}
}
The backgroundWorker methods in the Form:
void Form1_Shown(object sender, EventArgs e)
{
bgW.RunWorkerAsync();
bgW.WorkerSupportsCancellation = true;
}
void bgW_DoWork(object sender, DoWorkEventArgs e)
{
bgW.WorkerSupportsCancellation = true;
if(textBox1.InvokeRequired)
{
emails = autoComplete.getEmails();
collection.AddRange(emails.ToArray());
textBox1.Invoke(new MethodInvoker(delegate { textBox1.AutoCompleteCustomSource = collection; }));
}
for (int i = 100; i <= 100; i++)
{
bgW.ReportProgress(i);
if (i == 100)
{
label2.Invoke(new MethodInvoker(delegate { label2.Text = "Global Address List Loaded!"; }));
label2.Invoke(new MethodInvoker(delegate { label2.BackColor = System.Drawing.Color.LightGreen; }));
}
}
}
And upon closing the form:
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
bgW.CancelAsync();
}
Anyone have an idea about preventing this error?
Hans Passant: Sure, Environment.Exit(). Bam, gone.
Adding Enviroment.Exit(0); to the Form1_FormClosing() like Hans said did the trick everything gets closed when exiting the application now.
When adding files to the listView1 in this method i do have the property Items.
private void AddFiles(string strPath)
{
listView1.BeginUpdate();
listView1.Items.Clear();
iFiles = 0;
try
{
DirectoryInfo di = new DirectoryInfo(strPath + "\\");
FileInfo[] theFiles = di.GetFiles();
foreach(FileInfo theFile in theFiles)
{
iFiles++;
ListViewItem lvItem = new ListViewItem(theFile.Name);
lvItem.SubItems.Add(theFile.Length.ToString());
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortDateString());
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortTimeString());
listView1.Items.Add(lvItem);
}
}
catch(Exception Exc) { statusBar1.Text = Exc.ToString(); }
listView1.EndUpdate();
}
But now i want to add properties so when i'm doing mouse right click on a file it will show a contextmenu:
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
int index = listView1.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
listJobs.SelectedIndex = index;
Job job = (Job)listJobs.Items[index];
ContextMenu cm = new ContextMenu();
AddMenuItem(cm, "Run", QueueForRun, job).Enabled = !job.Pending;
AddMenuItem(cm, "Cancel run", CancelQueueForRun, job).Enabled = (job.State == JobState.Pending || job.State == JobState.Running);
AddMenuItem(cm, "Open folder", OpenFolder, job);
cm.Show(listJobs, e.Location);
}
}
}
This time i don't have IndexFromPoint and also not Items
Because IndexFromPoint() is a ListBox method, ListView has not. In ListView there is GetItemAt() method to achieve same result.
var item = listView.GetItemAt(e.Location.X, e.Location.Y);
if (item != null) {
listJobs.SelectedIndex = item.Index; // Assuming listJobs is a ListBox
}
EDIT: according to your comment if listJobs is a ListView too then it has not SelectedIndex but it has SelectedIndices, simply:
listJobs.SelectedIndices.Clear();
listJobs.SelectedIndices.Add(item.Index);
You have first to clear the list because, by default, MultiSelect is true then you may select multiple items.
im trying to pass an item from a listview1 to another listview2 and i want to check if the selected item is still not present in listview2. im trying to use a for loop to get each index of listview2 and compare it to the item selected in listview1. i tried using this but an error says that value of 0 is not a valid index.
private void listView1_DoubleClick(object sender, EventArgs e)
{
bool test = true;
for (int i = 0; i < listView1.Items.Count; i++)
{
string ls = listView2.Items[i].SubItems[0].Text;
string ps = listView1.Items[listView1.FocusedItem.Index].SubItems[0].Text;
if (ls.Trim() == ps.Trim())
{
test = false;
}
}
if (test == true)
{
ListViewItem ty = new ListViewItem(listView1.Items[listView1.FocusedItem.Index].SubItems[0].Text);
ty.SubItems.Add(listView1.Items[listView1.FocusedItem.Index].SubItems[1].Text);
listView2.Items.AddRange(new ListViewItem[] { ty });
}
else
{
MessageBox.Show("Student is already present in the list.","Cannot add to list",MessageBoxButtons.OK,MessageBoxIcon.Hand);
}
}
figured it out just as suggested. i used the foreach statement
private void listView1_DoubleClick(object sender, EventArgs e)
{
bool test = true;
string ps = listView1.Items[listView1.FocusedItem.Index].SubItems[0].Text;
foreach(ListViewItem disitem in listView2.Items)
{
string ls = disitem.SubItems[0].Text;
if (ps.Trim() == ls.Trim())
{
test = false;
}}
if (test == true)
{
ListViewItem ty = new ListViewItem(listView1.Items[listView1.FocusedItem.Index].SubItems[0].Text); ty.SubItems.Add(listView1.Items[listView1.FocusedItem.Index].SubItems[1].Text);
listView2.Items.AddRange(new ListViewItem[] { ty });
}
else
{
MessageBox.Show("Student is already present in the list.","Cannot add to list",MessageBoxButtons.OK,MessageBoxIcon.Hand);
}}
I'm trying to pass an item from a listview1 to another listview2 and I
want to check if the selected item is still not present in listview2.
I would simplify your method to something like:
private void listView1_DoubleClick(object sender, EventArgs e)
{
// Get the value of the selected item
string theItem = listView1.SelectedItems[0];
// Add to second list if it's not already in there
if(!listView2.Items.Contains(theItem))
{
listView2.Items.Add(theItem);
}
else
{
MessageBox.Show("Student is already present in the list.","Cannot add to list",MessageBoxButtons.OK,MessageBoxIcon.Hand);
}
}
private void listView1_DoubleClick(object sender, EventArgs e)
{
bool test = true;
var selectedItem = listView1.SelectedItems[0];
foreach(var item in listview2.Items)
{
string listview2Text = item.SubItems[0].Text;
string listview1Text = selectedItem.SubItems[0].Text;
if (listview2Text.Trim() == listview1Text.Trim())
{
test = false;
}
}
if (test == true)
{
//I am not sure exactly what you're trying to do if the test is true but I think you're trying to do this
listView2.Items.Add(selectedItem);
}
else
{
MessageBox.Show("Student is already present in the list.","Cannot add to list",MessageBoxButtons.OK,MessageBoxIcon.Hand);
}
}
I believe it should be something like:
private void listView1_DoubleClick(object sender, EventArgs e)
{
bool add = true;
string selected = listView1.Items[listView1.FocusedItem.Index];
foreach(ListViewItem item in listView2.Items)
if (selected.SubItems[0].Text == item.SubItems[0].Text)
{
add = false;
break;
}
if(add)
listView2.Items.Add(selected);
else
MessageBox.Show("Student is already present in the list.","Cannot add to list",MessageBoxButtons.OK,MessageBoxIcon.Hand);
}
but I am pretty unsure...
I have a listview which display the content from the database.I also have a refresh button in my form.Once the refresh button is clicked the listview is get updated once again.The problem is when the refresh button is clicked the already selected item in the listview is get removed from the focus.This is my code
private void btnRefresh_Click(object sender, EventArgs e)
{
//to refresh manually
this.Refresh();
listView1.Items.Clear();
/*btnEdit_Question.Enabled = true;
btnRepeat_Question.Enabled = true;
btnDelete_Question.Enabled = true;*/
GetData();
}
public void GetData()
{
try
{
now = DateTime.Now;
String time_date = now.ToString();
myConnection = new SqlConnection(connectString);
listView1.Items.Clear();
myConnection.Open();
String MyString1 = string.Format("SELECT " + data_variables.RES_TXT_STRING_COLUMN1 + "," + data_variables.RES_TXT_STRING_COLUMN2 + "," + data_variables.RES_TXT_STRING_COLUMN3 + "," + data_variables.RES_TXT_STRING_COLUMN4 + "," + data_variables.RES_TXT_STRING_COLUMN6 + " FROM " + data_variables.RES_TXT_STRING_QUESTION_TABLE);
com = myConnection.CreateCommand();
com.CommandText = MyString1;
dr = com.ExecuteReader();
ListViewItem itmX;
//Adding the Items To The Each Column
while (dr.Read())
{
itmX = new ListViewItem();
itmX.Text = dr.GetValue(0).ToString();
ListViewItem.ListViewSubItem aSubFooItem1 = new ListViewItem.ListViewSubItem(itmX, dr.GetValue(1).ToString()); //Creating subitems for the parent item
itmX.SubItems.Add(aSubFooItem1);
//Associating these subitems to the parent item
ListViewItem.ListViewSubItem aSubFooItem2 = new ListViewItem.ListViewSubItem(itmX, dr.GetValue(2).ToString()); //Creating subitems for the parent item
ListViewItem.ListViewSubItem aSubFooItem3 = new ListViewItem.ListViewSubItem(itmX, dr.GetValue(3).ToString()); //Creating subitems for the parent item
if (dr.GetValue(4).ToString() == "0")
{
aSubFooItem5 = new ListViewItem.ListViewSubItem(itmX, "No");
}
else
{
aSubFooItem5 = new ListViewItem.ListViewSubItem(itmX, "Yes");
}
if (dr.GetDateTime(2) < now && dr.GetDateTime(3) > now)
{
itmX.SubItems.Add(aSubFooItem2);
itmX.SubItems.Add(aSubFooItem3);
ListViewItem.ListViewSubItem aSubFooItem4 = new ListViewItem.ListViewSubItem(itmX, "In Progress");
itmX.SubItems.Add(aSubFooItem4);
itmX.SubItems.Add(aSubFooItem5);
}
else if (dr.GetDateTime(2) <= now)
{
itmX.SubItems.Add(aSubFooItem2);
itmX.SubItems.Add(aSubFooItem3);
ListViewItem.ListViewSubItem aSubFooItem4 = new ListViewItem.ListViewSubItem(itmX, "Expired");
itmX.SubItems.Add(aSubFooItem4);
itmX.SubItems.Add(aSubFooItem5);
}
else if (dr.GetDateTime(2) > now)
{
itmX.SubItems.Add(aSubFooItem2);
itmX.SubItems.Add(aSubFooItem3);
ListViewItem.ListViewSubItem aSubFooItem4 = new ListViewItem.ListViewSubItem(itmX, "Not Expired");
itmX.SubItems.Add(aSubFooItem4);
itmX.SubItems.Add(aSubFooItem5);
}
//add all the items ti listview
listView1.Items.Add(itmX);
//Adding colors
itmX.UseItemStyleForSubItems = false;
foreach (ListViewItem lvi in listView1.Items)
{
if (lvi.SubItems[4].Text=="Expired")
{
lvi.SubItems[4].BackColor = Color.Red;
}
else if (lvi.SubItems[4].Text == "Not Expired")
{
itmX.SubItems[4].BackColor = Color.Yellow;
}
else
{
itmX.SubItems[4].BackColor = Color.Green;
}
}
}
EventLog log = new EventLog(data_variables.RES_TXT_STRING_LOG_EVENT);
try
{
log.Source = data_variables.RES_TXT_STRING_LOG_SOURCE;
log.WriteEntry(data_variables.REX_TXT_STRING_MESSAGE_SUCCESSFUL, EventLogEntryType.Information);
}
if (listView_Selected_Index > -1)
{
//Keep the focus in the listview
this.listView1.Items[listView_Selected_Index].Focused = true;
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
now = DateTime.Now;
for (int i = 0; i < listView1.SelectedItems.Count; i++)
{
//Selecting the each values of the selected item from listview
listView_Selected_Index = listView1.SelectedIndices[i];
}
}
Can anyone help me how to remain the focus on the listview item even the refresh button is get clicked
You are removing original (some selected) items from the listview at the top of GetData().
You need to store somewhere what is selected before you read new data from database. Then after new data is displayed in listview you have to select items based on what was selected before data refresh.
//store selected items (id or sth else that identifies item)
GetData();
//restore selection (some of previously items may no longer exist)
In your code you only saving the last selected item not all of them.
for (int i = 0; i < listView1.SelectedItems.Count; i++)
{
//Selecting the each values of the selected item from listview
// here You are only saving last selected item
// instead of this do sth like
// selectedItems.Add(sth that identifies this item, not index)
listView_Selected_Index = listView1.SelectedIndices[i];
}
Also instead of doing it on every selectedIndexchanged You can do it only before data refresh unless you need it for some other reasons.
What you can do is, save the currently selected index of ListView1 in some temporary field and after calling GetData() method reset the selected index property of ListView1 by assigning value of temporary field to ListView1.SelectedIndex property
something like this:
private int _selectedIndex = -1;
private void btnRefresh_Click(object sender, EventArgs e)
{
_selectedIndex = listView1.SelectedIndex;
//to refresh manually
this.Refresh();
listView1.Items.Clear();
/*btnEdit_Question.Enabled = true;
btnRepeat_Question.Enabled = true;
btnDelete_Question.Enabled = true;*/
GetData();
listView1.SelectexIndex = _selectedIndex;
}