Listing a table of folders using C# - c#

I want to mimic the functionality of the following image using Visual C#:
This I know is not a textbox or a combobox or a richtext (Maybe).
I managed to get the add function, where I get directories and I can select them:
private void button8_Click(object sender, EventArgs e)
{
this.folderBrowserDialog1.ShowNewFolderButton = false;
this.folderBrowserDialog1.RootFolder = System.Environment.SpecialFolder.MyComputer;
DialogResult result = this.folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
// the code here will be executed if the user selects a folder
string path = this.folderBrowserDialog1.SelectedPath;
}
}
How do I list them like in the image, should I write it to an ini file, or XML file, and then if so how do I list it in the box as shown.
I also need to detect the OS and have few default folders in the list.

Not quite sure what you want, but the image shows a list with a string and bool value. So you can use something like this:
public class DirOptions
{
string Path = string.Empty;
bool IncludeSubDirs = false;
}
Then you can store your data inside a List<>:
var list = new List<DirOptions>();
To detect OS:
Please see this question Get OS Version / Friendly Name in C#

Related

Clear values loaded from a JSON file in a C# application

I have a C# very big C# application with a lot of values that are saved in a JSON file. At the very start, I can either do it fresh (i.e: choose new values as I enter in the values in the textboxes etc) or load an existing JSON file. There are no problems with either of that.
However, now what I want to be able to do is that if I load in an existing JSON file with said values, and if I go back then those values should be cleared up. Let me demonstrate all this more with examples.
So I have two modes- fresh and update. In fresh, I type in those values manually however in update, you are asked to upload a JSON file and then those values are loaded in their respective text boxes, check boxes etc.
As it stands now, if I have loaded in a JSON file and then I click "Back" to go to fresh mode, the values are not reset and my application loads in the values from the JSON file. I want to be able to clear those values and reset them. I don't know how to achieve this.
In the "browse" button where the user loads up the JSON file, I have this code:
private void Browse_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog
{
DefaultExt = ".json",
Filter = "JSON Files (*.json)|*.json"
};
Nullable<bool> result = dlg.ShowDialog();
if (result == true)
{
Configs.ConfigPath = dlg.FileName;
jsonFile.Text = dlg.FileName;
string userJson = File.ReadAllText(Configs.ConfigPath);
try
{
var json = JsonConvert.DeserializeObject<AppConfigs>(userJson);
try
{
CopyNotNulls(json, Configs.Default);
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
}
For the xaml of the text box where you load in the json file, I have this TextChanged event arg and if I manually remove what the user has loaded and delete the text in that text box, then that works fine. But I want it done so that whenever I go back from that page, it resets when I go back from the update page to fresh page.
If I understand the process of your application correctly you are loading the json file into an objet and the controls that display the data are bound to the object properties, right? the only thing you have to do to get rid of those values is to get a new object if you go the fresh route. Just do:
var json = new AppConfigs();
alternatively, if you want to keep some of the values you'd have to reset them, for example on the AppConfigs object you can add a public method that clears the fields you want to get rid of. That would look like this:
public class AppConfigs
{
public string stringProp { get; set; }
public bool boolProp { get; set; }
public int intProp { get; set; }
public AppConfigs()
{
// default values here
// or just call Clear();
stringProp = "";
boolProp = false;
intProp = 0;
}
public void Clear()
{
stringProp = "";
boolProp = false;
intProp = 0;
}
}
then you could call it on your button click:
json.Clear();

How to fix ListView.LargeImageList showing images twice

I am working on a piece of software, which compares memes and helps users organize memes on their computer. As a part of this I am using Windows.Forms to build a UI. This UI lets the user add folders to be checked for images, which can be compared to a set of known meme templates.
My issue arises when I try to show the user the found images. To do this I am using a ListView and the property LargeImageList to contain a tuple of the image and the name of the image file.
Here is the piece of code in question:
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
var ic = new ImageCollection();
var fbd = new FolderBrowserDialog();
fbd.Description = "Select meme folder or image.";
if (fbd.ShowDialog() == DialogResult.OK)
{
string[] files = Directory.GetFiles(fbd.SelectedPath);
foreach (var file in files)
{
if (!ic.CheckIfImage(file)) continue;
imageList1.Images.Add(Image.FromFile(file));
}
foreach (var file in files)
{
listView1.Items.Add($"{Path.GetFileNameWithoutExtension(file)}", i++);
}
}
}
This is an example of what the user sees when they first load in a folder. When the user tries to load in another folder this happens. It shows the images from the first folder, with the names of the image files from the second folder.
Does anyone know a fix for this issue? I have tried a variety of options in order to get around the issue. All from trying to clear the ImageList used to contain the images, to trying my hand at controlling when the ListView updates. None of this has worked. I have also tried googling the issue, but with no luck of finding a fix.
Thank you in advance.
If you want to show the content of a single folder at the time, then dispose of the objects in your ImageList.
If you instead want to show the content of more than one folder, you need to specify the new index of the image added. You're instead adding a new Item in the ListView using the same index reference:
int i = 0;
//(...)
listView1.Items.Add($"{Path.GetFileNameWithoutExtension(file)}", i++);
The indexer (i) always starts from 0, thus the ListView Item will use the images in your Imagelist starting from the Image at Index[0] each time. The new images won't ever be shown.
You can use the ImageList.Images.Count value, representing the number of Images already added to the ImageList, as base and increment the indexer starting from this value:
private void button1_Click(object sender, EventArgs e)
{
int i = imageList1.Images.Count;
var ic = new ImageCollection();
var fbd = new FolderBrowserDialog();
fbd.Description = "Select meme folder or image.";
if (fbd.ShowDialog() == DialogResult.OK)
{
foreach (var file in Directory.GetFiles(fbd.SelectedPath))
{
if (!ic.CheckIfImage(file)) continue;
imageList1.Images.Add(new Bitmap(file, true));
listView1.Items.Add($"{Path.GetFileNameWithoutExtension(file)}", i++);
}
}
}
If you allow to remove an Image from the ListView, you should also remove it from the ImageList: this implies that you need to re-index all the ListView Items starting from the Item that follows the one removed.
Remember to dispose of the Images you remove from the ImageList.

how to go next line in ListBox?

hey guys i wanna to load a File path in my listBox.
everything is ok
i just have a problem that is when i Close the app and then open it again
loaded files are in the one lane and it recognize them as one item in listBox
i tried to use "\n" , "\r" none of these works...
so what u guys suggest?
(i save user changes in App Setting to read them later)
private void Form1_Load(object sender, EventArgs e)
{
if (Properties.Settings.Default.FileList != string.Empty)
{
fileListBox.Items.Add(Properties.Settings.Default.FileList);
}
UnlockForm f2 = new UnlockForm();
if (Properties.Settings.Default.PasswordCheck == true)
f2.ShowDialog();
else
return;
}
private void button1_Click_1(object sender, EventArgs e)
{
op = new OpenFileDialog();
op.Title = "Select your stuff";
op.Filter = "All files (*.*)|*.*";
if (op.ShowDialog() == DialogResult.OK)
{
fileName = op.FileName;
fileListBox.Items.Add(fileName);
}
Properties.Settings.Default.FileList += fileName+"\n";
Properties.Settings.Default.Save();
}
When creating the property in settings designer:
Set the name to whatever you want, for example Files
Set the type as System.Collections.Specialized.StringCollection
Set the scope as User
If you want to have some default values, use ... in Value cell to edit default value.
Then you can easily set it as DataSource of the ListBox.
listBox1.DataSource = Properties.Settings.Default.Files;
Also to add some values:
Properties.Settings.Default.Files.Add("something");
Properties.Settings.Default.Save();
If you added something to the Files, if you want the ListBox shows the changes, set DataSource to null and then to Files again.
It looks like you have defined your FileList as String in our App Settings. There are two ways you can approach this.
a) Using FileList as Collection.
You can change the Type of FileList to StringCollection in your App Settings. Then, you can add items to your list as follows
fileListBox.Items.AddRange(Properties.Settings.Default.FileList.Cast<string>().ToArray());
b) Using FileList as String.
If you really want to retain Properties.Settings.Default.FileList as string, you would need to split it on the run using your delimiter character (let's say ';')
fileListBox.Items.AddRange(Properties.Settings.Default.FileList.Split(new[] { ';' },StringSplitOptions.RemoveEmptyEntries));
In your case, a collection might be a better approach unless you have specific reasons outside the scope of OP to use string.

Strip leading characters from a directory path in a listbox in C#

So i am attempting to teach myself C#, I have a program that I originally wrote in batch and am attempting to recreate in C# using WPF. I have a button that allows a user to set a directory, that directory selected is then displayed in a text box above a listbox which adds every subfolder, only first level, to the listbox. Now all this works fine but it writes out the entire directory path in the listbox. I have been trying to figure out how to strip the leading directory path off the list box entries for over an hour to no avail. Here is what I have so far:
private void btn_SetDirectory_Click(object sender, RoutedEventArgs e)
{
//Create a folder browser dialog and set the selected path to "steamPath"
var steamPath = new FolderBrowserDialog();
DialogResult result = steamPath.ShowDialog();
//Update the text box to reflect the selected folder path
txt_SteamDirectory.Text = steamPath.SelectedPath;
//Clear and update the list box after choosing a folder
lb_FromFolder.Items.Clear();
string folderName = steamPath.SelectedPath;
foreach (string f in Directory.GetDirectories(folderName))
{
lb_FromFolder.Items.Add(f);
}
}
Now I tried changing the last line to this, and it did not work it just crashed the program:
foreach (string f in Directory.GetDirectories(folderName))
{
lb_FromFolder.Items.Add(f.Substring(f.LastIndexOf("'\'")));
}
I am fairly certain that the LastIndexOf route is probably the right one but I am at a dead end. I apologize if this is a dumb question but this is my first attempt at using C#. Thanks in advance.
This can solve your issue
string folderName = steamPath.SelectedPath;
foreach (string f in Directory.GetDirectories(folderName))
{
// string[] strArr = f.Split('\\');
lb_FromFolder.Items.Add(f.Split('\\')[f.Split('\\').Length-1]);
}
You can use this code:
string folderName = steamPath.SelectedPath;
foreach (string f in Directory.GetDirectories(folderName))
{
lb_FromFolder.Items.Add(f.Remove(0,folderName.Length));
}

Filling Listview & Imagelist selected item confusion c#

I new to programming and C# and seemed to have worked myself into a bit muddle with the above.
What i am trying to do is create a front end for the living room media pc nothing to fancy to start with as i understand this is a mamoth task for a total noobie like me.
Ive flapped about and am totally fine with launching external exe's,storing/loading resouces ect.. and been very happy with my results for my 2 week surfing.
So im starting off my project by just launching an emulator to start with and what i would like to do is scan a folder for zip files and image files and if it finds matching image and zip files it displays an image in a list view for each zip found.
So i populate my listboxes like this and get my 2 listboxes showing the stuff i want to see.
PopulateListBox(listBox1, "\\SomePath\\", "*.zip");
PopulateListBox(listBox2, "\\Images\\", "*.jpg");
private void PopulateListBox(ListBox lsb, string Folder, string FileType)
{
DirectoryInfo dinfo = new DirectoryInfo(Folder);
FileInfo[] Files = dinfo.GetFiles(FileType);
foreach (FileInfo file in Files)
{
lsb.Items.Add(file.Name);
}
}
So i now have my 2 listboxes and can see i have game1.zip and game1.jpg, great now i can populate my listview with the game1 image and launch the emulator he say's simple.
This is how i am currently populating the listview.
PopulateListView();
private void PopulateListView()
{
if (listBox1.Items.Contains("game1.zip"))
{
if (File.Exists("\\Images\\game1.jpg"))
{
imageList1.Images.Add(Image.FromFile("\\Images\\game1.jpg"));
listView1.Items.Add("", 0);
}
}
if (listBox1.Items.Contains("game2.zip"))
{
if (File.Exists("\\Images\\game2.jpg"))
{
imageList1.Images.Add(Image.FromFile("\\Images\\game2.jpg"));
listView1.Items.Add("", 1);
}
}
}
This is how i am currently launching and it works ok.
// launch item
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (listView1.Items[0].Selected == true)
{
string rom = "\\" + listBox1.Items[0].ToString();
// Launch code in here
}
if (listView1.Items[1].Selected == true)
{
string rom = "\\" + listBox1.Items[1].ToString();
// Launch code in here
}
}
So what the problem you may ask ?
Instead of keep typing in all that info for each item i want to use some kind of statment if possible and i dont know what to search for which does not help.
The image name will allways match the zip name just need to loose the file extensions so to populate the listview somthing like this.
if (listbox1 item = listbox2 item)
{
add to imagelist and listview automaticly with same index
}
Then i want to be able to launch just using somthing like this.
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
string rom = "\\" + listview.selected.item.tostring;
// Launch code in here
}
Hope im making sense im at my witts end.
Regards
Derek
If i understand correctly, you want to read, match and show programmatically all images and zips that are the same and when the user clicks a list view row to start the rom. This can be done as follows:
read all images - there is no need to check if the file exists, because if it does not, then GetFiles will not find it!
read all roms - same as above!
take all names that have both image and zip file (that are the same)
fill image list and list view at the same time
bind list view item with the correct image
store rom location
handle mouse click on row and fetch rom location
do something with rom file
The code:
public ListForm()
{
InitializeComponent();
// path to images and roms
const string location = #"d:\temp\roms\";
// bind image list with list view
listViewControl.SmallImageList = imageList;
// get all images without extension
var images = System.IO.Directory.GetFiles(location, "*.gif").Select(f => System.IO.Path.GetFileNameWithoutExtension(f)).ToList();
// get all roms without extension
var zips = System.IO.Directory.GetFiles(location, "*.zip").Select(f => System.IO.Path.GetFileNameWithoutExtension(f)).ToList();
// find all entries (images and zips) that have the same name
var matching = images.Intersect(zips);
var imageIndex = 0;
// fill image list and list view at the same time and store rom location
foreach (var match in matching)
{
// path to file without extension
var file = System.IO.Path.Combine(location, match);
// add image to image list
imageList.Images.Add(match, Bitmap.FromFile(string.Format("{0}.gif", file)));
// create list view item
var lvi = new ListViewItem(match);
// and set list view item image
lvi.ImageIndex = imageIndex;
// store rom location
lvi.Tag = string.Format("{0}.zip", file);
imageIndex++;
// and show
listViewControl.Items.Add(lvi);
}
}
private void listViewControl_MouseClick(object sender, MouseEventArgs e)
{
// when user clicks an item, fetch the rom location and go
var item = listViewControl.GetItemAt(e.X, e.Y);
if (item != null)
{
var pathToRom = item.Tag as string;
// do something with rom ...
}
}
There is no need to handle the image list and the list view separately. The output looks like:
you can Populate the images using the names from the listView:
private void PopulateListView()
{
foreach (string curr in listBox1.Items)
{
string changed = "\\Images\\" + curr.Replace(".zip", ".jpg");
if (File.Exists(changed))
{
imageList1.Images.Add(Image.FromFile(changed));
listView1.Items.Add("", 1);
}
}
}
and use the selected item in the MouseDoubleClick event
// launch item
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
string selected = (string) listBox1.SelectedItem;
string rom = "\\" + selected;
// Launch code in here
}
If I'm understanding your problem correctly, you can switch out your tower of if statements with this:
var item = listView1.SelectedItem
string rom = "\\" + item.ToString()
// Launch code in here
And to populate it, you can change this:
if (listBox1.Items.Contains("game2.zip"))
{
if (File.Exists("\\Images\\game2.jpg"))
{
imageList1.Images.Add(Image.FromFile("\\Images\\game2.jpg"));
listView1.Items.Add("", 1);
}
}
To this:
List<string> files = new List<string> { "game1.zip", "game2.zip" };
var index = 0;
foreach (var file in files)
{
if (File.Exists("\\Images\\" + file))
{
imageList1.Images.Add(Image.FromFile("\\Images\\" + file.Replace(".zip", ".jpg")));
listView1.Items.Add("", index);
index++;
}
}

Categories