I remember in vb6 there was a control that was similar to a dropbox/combobox that you can select the drive name. It raises an event which you can then set another control which enumerate files in listbox. (in drive.event you do files.path = drive.path to get this affect).
Is there anything like this in C#? a control that drops down a list of available drives and raises an event when it is changed?
There's no built-in control to do that, but it's very easy to accomplish with a standard ComboBox. Drop one on your form, change its DropDownStyle to DropDownList to prevent editing, and in the Load event for the form, add this line:
comboBox1.DataSource = Environment.GetLogicalDrives();
Now you can handle the SelectedValueChanged event to take action when someone changes the selected drive.
After answering this question, I've found another (better?) way to do this. You can use the DriveInfo.GetDrives() method to enumerate the drives and bind the result to the ComboBox. That way you can limit which drives apppear. So you could start with this:
comboBox1.DataSource = System.IO.DriveInfo.GetDrives();
comboBox1.DisplayMember = "Name";
Now comboBox1.SelectedValue will be of type DriveInfo, so you'll get lots more info about the selected game. And if you only want to show network drives, you can do this now:
comboBox1.DataSource = System.IO.DriveInfo.GetDrives()
.Where(d => d.DriveType == System.IO.DriveType.Network);
comboBox1.DisplayMember = "Name";
I think the DriveInfo method is a lot more flexible.
While Matt Hamiltons answer was very correct, I'm wondering if the question itself is. Because, why would you want such a control? It feels very Windows 95 to be honest. Please have a look at the Windows User Experience Interaction Guidelines: http://msdn.microsoft.com/en-us/library/aa511258.aspx
Especially the section about common dialogs:
http://msdn.microsoft.com/en-us/library/aa511274.aspx
I would approach this with:
foreach (var Drives in Environment.GetLogicalDrives())
{
DriveInfo DriveInf = new DriveInfo(Drives);
if (DriveInf.IsReady == true)
{
comboBox1.Items.Add(DriveInf.Name);
}
}
With the help of Drive.IsReady u can avoid having DeviceNotReady or DeviceUnavailable issues.
Bonus:
Also here is a simple "ChooseFile" example which includes a ComboBox for drives, a TreeView for folders and the last a ListBox for files.
namespace ChosenFile
{
public partial class Form1 : Form
{
// Form1 FormLoad
//
public Form1()
{
InitializeComponent();
foreach (var Drives in Environment.GetLogicalDrives())
{
DriveInfo DriveInf = new DriveInfo(Drives);
if (DriveInf.IsReady == true)
{
comboBox1.Items.Add(DriveInf.Name);
}
}
}
// ComboBox1 (Drives)
//
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedItem != null)
{
ListDirectory(treeView1, comboBox1.SelectedItem.ToString());
}
}
// ListDirectory Function (Recursive Approach):
//
private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
// Create Directory Node
//
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
try
{
foreach (var directory in directoryInfo.GetDirectories())
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
catch (Exception ex)
{
UnauthorizedAccessException Uaex = new UnauthorizedAccessException();
if (ex == Uaex)
{
MessageBox.Show(Uaex.Message);
}
}
return directoryNode;
}
// TreeView
//
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
listBox1.Items.Clear();
listBox1.Refresh();
PopulateListBox(listBox1, treeView1.SelectedNode.FullPath.ToString(), "*.pdf");
}
// PopulateListBox Function
//
private void PopulateListBox(ListBox lsb, string Folder, string FileType)
{
try
{
DirectoryInfo dinfo = new DirectoryInfo(Folder);
FileInfo[] Files = dinfo.GetFiles(FileType);
foreach (FileInfo file in Files)
{
lsb.Items.Add(file.Name);
}
}
catch (Exception ex)
{
MessageBox.Show("An error occurred while attempting to load the file. The error is:"
+ System.Environment.NewLine + ex.ToString() + System.Environment.NewLine);
}
}
// ListBox1
//
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedItem != null)
{
//do smt here!
MessageBox.Show(listBox1.SelectedItem.ToString());
}
}
}
}
Just like the old times in VB6.
A comboBox and this little code will do the job. Kindest regards! Luis:
comboBox1.DataSource = System.IO.DriveInfo.GetDrives()
.Where(d => d.DriveType == System.IO.DriveType.Network).ToList();
comboBox1.DisplayMember = "Name";
Related
I am trying to come up with a solution where I can search items inside a combo box that contain certain word/phrase. I tried using the AutoComplete text box functionality, but that only searches for the first word which is no good to me.
I have followed the example provided at https://social.msdn.microsoft.com/Forums/vstudio/en-US/4c229a73-cdad-4fa3-95db-97f9ff7810c1/autocomplete-match-on-contains-not-startswith?forum=netfxbcl
I have initiated 2 lists
public List<string> listOnit = new List<string>();
public List<string> listNew = new List<string>();
I then load the data into a comboBox
if (rdr.HasRows == true)
{
// var source = new List<string>();
while (rdr.Read())
{
// myCollectionSales.Add(rdr[0].ToString());
listOnit.Add(rdr[0].ToString());
}
rdr.Close();
//textBox1.AutoCompleteCustomSource = myCollectionSales;
comboBox1.Items.AddRange(listOnit.ToArray());
}
and have a TextUpdate event handler to filter the list when text has changed
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
foreach (var item in listOnit)
{
if (item.Contains(this.comboBox1.Text))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
I am coming across a problem where the search results don't return what I expect. For example, I search for the string "Bud" and I only get the following results
http://prntscr.com/ppkatd
While in the database, there is also Budweiser 33cl and Keg Budweiser (http://prntscr.com/ppkbu4), for example, which is fetched on the first list.
Should I be using a different method, rather than "Contains"?
Perhaps you are using different cases?
Try with .ToLower():
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
comboBox1.Items.Clear();
listNew.Clear();
foreach (var item in listOnit)
{
if (item.ToLower().Contains(this.comboBox1.Text.ToLower()))
{
listNew.Add(item);
}
}
comboBox1.Items.AddRange(listNew.ToArray());
comboBox1.SelectionStart = this.comboBox1.Text.Length;
Cursor = Cursors.Default;
comboBox1.DroppedDown = true;
}
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");
I'm really new to coding
I have a treeview that refreshes with a timer.
How can i make sure i keep my selected node highlighted every time it refreshes
Appreciate any help
Thanks
Here is the code that I have:
private void PopulateTree(ListObjectsResponse buckets)
{
treeView1.Nodes.Clear();
List<TreeItem> items = new List<TreeItem>();
foreach (S3Object obj in buckets.S3Objects)
{
treeView1.Nodes.Add(new TreeNode(obj.Key));
}
}
private void button4_Click_1(object sender, EventArgs e)
{
timer1.Enabled = true;
existingBucketName = label3.Text + "-DP";
AmazonS3Client client = new AmazonS3Client();
ListObjectsRequest listRequest = new ListObjectsRequest
{
BucketName = existingBucketName,
};
try
{
ListObjectsResponse listResponse;
listResponse = client.ListObjects(listRequest);
PopulateTree(listResponse);
}
catch
{
timer1.Enabled = false;
MessageBox.Show("There is no folder for this user");
}
}
Assuming that o.Key is a string, and that each string is unique and occurs at most once in buckets.S3Objects, try saving the selected value before repopulating the TreeView, then select it again afterwards.
private void PopulateTree(ListObjectsResponse buckets)
{
// Since you're about to clear out all current TreeNode instances, storing a
// reference to SelectedNode is not enough. You're setting o.Key as the Text
// for each TreeNode, so save the selected node's Text value.
var selectedText
= treeView1.SelectedNode == null ? "" : treeView1.SelectedNode.Text;
// Repopulate your TreeView with new TreeNodes
treeView1.Nodes.Clear();
treeView1.Nodes.AddRange(buckets.S3Objects.Select(o => new TreeNode(o.Key)).ToArray())
// Look for the TreeNode with the same Text that you had selected before.
// If it's not found, then SelectedNode will be set to null
treeView1.SelectedNode =
= treeView1.Nodes.Cast<TreeNode>()
.SingleOrDefault(n => n.Text == selectedText);
}
Several of the above methods, such as Select, Cast, and SingleOrDefault, are part of LINQ.
Assuming this is ASP.NET (not ASP.NET MVC) that you're talking about, you would do this in the Page_Load() event handler. Be sure to check whether IsPostBack == true
For example,
private void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// set selected node here
}
}
If you are using ASP.NET MVC then just store the property in the ViewBag.
The user can click an item in a ListBox as follows:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
textBox2.Clear();
listBox2.Items.Clear();
string[] p =
Directory.GetFiles(
textBoxDir.Text,
listBox1.SelectedItem.ToString(),
SearchOption.AllDirectories);
foreach (string open in p)
......
}
All is fine. However if the user clicks on an empty space in the ListBox, it displays the following error:
System.NullReferenceException
This is because of this line of code:
string[] p =
Directory.GetFiles(
textBoxDir.Text,
listBox1.SelectedItem.ToString(),
SearchOption.AllDirectories);
Does anyone have a clever work around? Or suggest an aalternative to my code?
The workaround is to check for a null value, and exit early.
if (listBox1.SelectedItem == null)
{
return;
}
This avoids the nesting introduced by the other answers, which makes the code less readable.
You can check SelectedIndex before that line:
if(listBox2.SelectedIndex < 0)
return;
How about doing a
if(listBox1.SelectedItem != null){
// ... do your work with listBox1.SelectedItem here
}
that should prevent that error from happening.
How about
if (listBox1.SelectedItem != null)
{
string[] p = Directory.GetFiles(textBoxDir.Text, listBox1.SelectedItem.ToString(), SearchOption.AllDirectories);
}
Full Code
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedItem != null)
{
textBox2.Clear();
listBox2.Items.Clear();
string[] p = Directory.GetFiles(textBoxDir.Text, listBox1.SelectedItem.ToString(), SearchOption.AllDirectories);
foreach (string open in p)
...... }
}
}
just check first if listbox1.SelectedItem is empty or not prior to calling this line:
string[] p = Directory.GetFiles(textBoxDir.Text, listBox1.SelectedItem.ToString(), SearchOption.AllDirectories);
I had a similar problem. This is the shortest way i fixed it.
private void button1_Click(object sender, EventArgs e)
{
radioButton1.Checked = !radioButton1.Checked;
string indicadorPais = "Something";
if (listaPaises.SelectedItem != null)
{
indicadorPais = listaPaises.SelectedItem.ToString();
label1.Text = indicadorPais;
}
As a sidenote. My condition originally was comparing listaPaises.SelectedItem.ToString() != null. This broke because i was casting null to a string. The code im sending works fine.
However none of these allow you to go back in and re-select from the list box. Still working on that issue - will update.
while (user == null) {
try {
user = this.lstAdministratorName.SelectedItem.ToString();
} catch {
lstAdministratorName.ClearSelected();
return;
}
}
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)
{
}
}
}