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.
Related
I would like to make a file explorer with Windows Forms, i already have done a few things, but when i would like to use the DoubleClick event of my ListView I dont know how to code that file explorer needs to act differently when I make the doubleclick on a file or a folder.
My goal is:
Clicking on a file - Loads its text into a TextBox
Clicking on a directory - Opens it and loads it into the listview.
I know how to do 1. and 2. as well, I just don't know how can I make my DoubleClick function know what the selected item in ListView was 1. or 2.
I build my ListView like this:
private void miOpen_Click(object sender, EventArgs e)
{
InputDialog dlg = new InputDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
DirectoryInfo parentDI = new DirectoryInfo(dlg.Path);
listView1.Items.Clear();
try
{
foreach (DirectoryInfo df in parentDI.GetDirectories())
{
ListViewItem lvi = new ListViewItem(new string[] {
df.Name, df.Parent.ToString(),
df.CreationTime.ToShortDateString(), df.FullName });
listView1.Items.Add(lvi);
}
foreach (FileInfo fi in parentDI.GetFiles())
{
ListViewItem lvi = new ListViewItem(new string[] {
fi.Name, fi.Length.ToString(),
fi.CreationTime.ToShortDateString(), fi.FullName } );
listView1.Items.Add(lvi);
}
}
catch { }
}
}
Add the DirectoryInfo or the FileInfo objects to the Tag property of the ListViewItem. I.e
...
var lvi = new ListViewItem(new string[] {
df.Name,
df.Parent.ToString(),
df.CreationTime.ToShortDateString(),
df.FullName
});
lvi.Tag = df;
listView1.Items.Add(lvi);
...
or for the file info:
lvi.Tag = fi;
Then, after having selected an item in the listview:
private void btnTest_Click(object sender, EventArgs e)
{
// Show the first item selected as an example.
if (listView1.SelectedItems.Count > 0) {
switch (listView1.SelectedItems[0].Tag) {
case DirectoryInfo di:
MessageBox.Show($"Directory = {di.Name}");
break;
case FileInfo fi:
MessageBox.Show($"File = {fi.Name}");
break;
default:
break;
}
}
}
Try this code:
FileAttributes fileAttributes = File.GetAttributes("C:\\file.txt");
if (fileAttributes.HasFlag(FileAttributes.Directory))
Console.WriteLine("This path is for directory");
else
Console.WriteLine("This path is for file");
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 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
im making a file explorer tool in c# .. im using ListView to explore files
but i have an issue when i copy items(files)
public ListView.SelectedListViewItemCollection copiedItems;
private void btnCopy_Click(object sender, EventArgs e)
{
copiedItems = listView1.SelectedItems;
infoLabel.Text = "Item(s) copied to clipboard.";
}
private void Paste()
{
if (copiedItems != null)
{
foreach (ListViewItem item in copiedItems)
{
if (File.Exists(item.ToolTipText))
{
if (MessageBox.Show(item.ToolTipText + "is already exists\r\nDo you want to overwrite it?"
, "Overwrite", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) == DialogResult.OK)
{
File.Copy(item.ToolTipText, currAddress, true);
infoLabel.Text = "Item(s) Pasted.";
}
return;
}
File.Copy(item.ToolTipText, currAddress, false);
infoLabel.Text = "Item(s) Pasted.";
}
}
}
when i change the folder that i am into(currAddress) .. the paste doesn't work because the
ListView.SelectedListViewItemCollection copiedItems
changed to null. .. here's my explorer code
private void DirRecursive(string path)
{
DirectoryInfo dir = new DirectoryInfo(path);
currAddress = path;
txtAddress.Text = path;
_iconListManager.ClearLists();
listView1.Items.Clear();
foreach (DirectoryInfo folder in dir.GetDirectories())
{
if ((folder.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
continue;
ListViewItem item = new ListViewItem();
item.Text = folder.Name;
item.Tag = (object)folder.Parent;
item.ToolTipText = folder.FullName;
item.ImageIndex = _iconListManager.AddFolderIcon(folder.FullName);
listView1.Items.Add(item);
}
foreach (FileInfo file in dir.GetFiles())
{
if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
continue;
ListViewItem item = new ListViewItem();
item.Text = file.Name;
item.Tag = (object)file.Directory.Parent;
item.ToolTipText = file.FullName;
item.ImageIndex = _iconListManager.AddFileIcon(file.FullName);
item.SubItems.Add(CnvrtUnit(file.Length));
listView1.Items.Add(item);
}
is there any explanation why copiedItems changed to null and how can i fix it ?
thanks in advance :)
Instead of
public ListView.SelectedListViewItemCollection copiedItems;
use
public List<string> copiedItems;
Change btnCopy_Click to this:
private void btnCopy_Click(object sender, EventArgs e)
{
copiedItems = listView1..SelectedItems.Cast<ListViewItem>().Select(li => li.ToolTipText).ToList();
infoLabel.Text = "Item(s) copied to clipboard.";
}
change Paste to this:
private void Paste()
{
if (copiedItems != null)
{
foreach (string item in copiedItems)
{
if (File.Exists(item))
{
if (MessageBox.Show(item + "is already exists\r\nDo you want to overwrite it?"
, "Overwrite", MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) == DialogResult.OK)
{
File.Copy(item, currAddress, true);
infoLabel.Text = "Item(s) Pasted.";
}
return;
}
File.Copy(item, currAddress, false);
infoLabel.Text = "Item(s) Pasted.";
}
}
}
I believe "listview1.SelectedItems" is just giving you a reference to the selected items. This means that "copiedItems" points to the same object as "listview1.SelectedItems". This is why when you clear the listview1 items in DirRecursive you clear the copiedItems.
You need to get a separate copy of the items. To do this you should probably use something like this:
List<ListViewItem> copiedItems = new List<ListViewItem>();
foreach (ListViewItem item in listView1.Items)
{
copiedItems.Add((ListViewItem) item.Clone());
}
The variable copiedItems isn't actually storing items, but rather storing a reference to where the selected items are. Or something to that effect. If the same items are selected at the time of the paste, you will be ok. But once the items are deselected in your list view, your copiedItems variable will now be an empty list. You need to explicitly copy the items that are selected when the copy button is pressed. The following sample program illustrates what I'm talking about. To make this run, create a new WinForms project, drag a ListView and two Button controls onto the form and replace the code in Form1.cs with the following.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
ListView.SelectedListViewItemCollection items1;
List<int> items2;
public Form1()
{
InitializeComponent();
items2 = new List<int>();
}
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
listView1.Items.Add(i.ToString());
}
}
private void button1_Click(object sender, EventArgs e)
{
items1 = listView1.SelectedItems;
foreach (var item in listView1.SelectedItems)
{
ListViewItem lvItem =(ListViewItem)item;
items2.Add(int.Parse(lvItem.Text));
}
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
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;
}