How to save from a listbox - c#

I am attempting to save items from a listbox to a file; I have tried using things like
listbox.items
listbox.items.addrange
listbox.items.count
listbox.items.text (which doesn't give me an error but it also doesn't save)
Here is code:
private void button2_Click(object sender, EventArgs e)
{
if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
File.WriteAllText(saveFileDialog1.FileName, listBox1.Items.Count);
}
}

File.WriteAllText expects two items: a filepath, and the string to write (as a String):
You gave it:
ListBox.Items (a collection)
ListBox.Items.AddRange (a function)
ListBox.Items.Count (Valid, but not related to the actual items because it is just the count)
ListBox.Items.Text (what????) (this probably doesn't compile, as I'm not aware of that property)
You need to iterate through all the items, joining them all if you really want to use File.WriteAllText.
Something like:
File.WriteAllText(saveFileDialog1.FileName, String.Join(",", listBox1.Items));
//If the above doesn't do the cast implicitly, and its always better to be explicit!
File.WriteAllText(saveFileDialog1.FileName, String.Join(",", listBox1.Items.Cast<string>()));
String.Join
There are lots of other ways to generate the output of course, but the short of it is that you need to iterate each element in the Items collection and write it out to the file individually, or use a function like String.Join to do it all in one go.

You could loop through the items and create a string that contains all of them, then write that string to the file.
string itemString = "";
foreach (Item item in listbox1.Items)
{
itemString+=item.Text;
}
File.WriteAllText(saveFileDialog1.FileName, itemString);
You would probably want to add some sort of delimiter with each item, a comma, or a newline character or something so the file doesn't look like gibberish.

To save the items from listBox:
private void SaveItems()
{
using(StreamWriter sw = new StreamWriter("file.txt"))
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
sw.WriteLine(listBox1.Items[i]);
}
}
}
To load the items to listBox:
private void LoadItems()
{
using(StreamReader sr = new StreamReader("file.txt"))
{
while (!sr.EndOfStream)
{
listBox1.Items.Add(sr.ReadLine());
}
}
}

If you want to store every item in a ListBox into a file, it would be best to use File.WriteAllLines(String, String[]).
File.WriteAllLines(saveFileDialog1.FileName,
listBox1.Items.OfType<ListViewItem>().Select(i => i.Text).ToArray());

Related

Delete the current element in an array

How can I delete the current element of an array inside a foreach-loop?
My program gets data form a DB and sends it to a new one via HTTP requests. Now I want to post a JSON string to my new DB. If it was a success I want to delete the current array item which I'm working with. Something like this.
foreach(var item in array)
{
bool decide = method.DoSomething();
if(decide == true)
{
//delete current item
}
}
since you cannot delete items from an array and change the size of it here is a loop approach using a second collection
List<itemClass> keepCollection = new List<itemClass>();
foreach(var item in array)
{
bool decide = method.DoSomething();
if(decide == false)
{
keepCollection.Add(item);
}
}
If you need it again in array form just call ToArray()
var finalResult = keepCollection.ToArray();
appraoch with Linq which creates a new array with valid elements and overwrites the existing array
array = array.Where(x => !method.DoSomething(x)).ToArray(); //select valid elements
there are 2 ways (both were tested)
foreach (var item in array.ToList())
{
bool decide = method.DoSomething();
if (decide == true)
{
item.Remove();
}
}
and
for ( i=0; i < array.Length; i++)
{
bool decide = method.DoSomething();
if (decide == true)
{
array[i].Remove();
}
}
Whenever you want to delete entries from a collection, you should never loop through that collection from beginning to end, but always from end back to beginning.
By the way, C# does not allow you deleting entries from a collection while looping through that collection using a foreach loop.

Append clipboard text to a listbox

So I created a variable to hold my clipboard text and I have no idea on how to append it to a listbox.
This is as far as I got..
private void clipboardBtn_Click(object sender, EventArgs e)
{
string items = Clipboard.GetText();
List<string> _items = new List<string>();
_items.AddRange(items);
}
but that throws me this error..
Argument 1: cannot convert from 'string' to
'System.Collections.Generic.IEnumerable'
What's causing this and how do I fix it? Is this even the correct way of appending text to the listbox?
-UPDATE-
I got this now but everytime I click the button it overwrites the old one instead of appending a new item to the listbox
string items = Clipboard.GetText();
List<string> _items = new List<string>();
_items.Add(items);
listBox1.DataSource =_items;
How do i append a new item?
Clipboard.GetText has the signature
public static string GetText()
but List<T>.AddRange has the signature
public void AddRange( IEnumerable<T> collection )
So essentially you're trying to add a string as an IEnumerable<T> which gives you the above error.
Better use List<T>.Add for that purpose like that:
_items.Add(items);
your question is about List object and not about ListBox control.
the AddRange() method requires a collection, you can transform your string to a collection (Array) by using Split.
private void clipboardBtn_Click(object sender, EventArgs e)
{
string YourGetClipBoardTextString = "aaa;bbb;ccc;ddd";
List<string> _items = new List<string>();
_items.AddRange(YourGetClipBoardTextString.Split(';').ToArray()); // you can split the string by any char seperator ";" " ", "," etc...
}
if you dont need to split the string just use the Add() method:
_items.Add(YourGetClipBoardTextString);
After your update, you can append new items to a listbox in that manner:
foreach (string itm in _items)
{
listBox1.Items.Add(itm);
}
since you're creating new "_items" on every click, you cannot see the old items. try like this,
List<string> _items = new List<string>();
private void clipboardBtn_Click(object sender, EventArgs e)
{
string items = Clipboard.GetText();
_items.Add(items);
listBox1.DataSource =_items;
}
_items declared outside of method scope.
Your problem is that you are initializing a new list each time:
string items = Clipboard.GetText();
List<string> _items = new List<string>();//<New list here results in removal of existing item
_items.Add(items);
listBox1.DataSource =_items;
Try something like this:
string items = Clipboard.GetText();
List<string> _items = listBox1.DataSource as List<string>;// You may have type casting issues here -
_items.Add(items);
listBox1.DataSource =_items;
First you need to split the clipboard contents into strings for each line, then you need to add them to the list box:
string[] items = Clipboard.GetText().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
listBox1.Items.AddRange(items);
If you don't want to have a separate listBox item for each line, just do this:
listBox1.Items.Add(Clipboard.GetText());

Directory.GetFiles error

my code
private void m1()
{
List<string> list = new List<string>();
foreach (string str in Directory.GetFiles("a1"))
{
if (Path.GetExtension(str).Contains("txt")) -- get all txt file in a1 folder
{
list.Add(Path.GetFileNameWithoutExtension(str));
}
}
base.SuspendLayout();
this.Combobox_1.Items.AddRange(list.ToArray());
base.ResumeLayout();
}
but combobox cannot list txt file in folder a1
Please helpme.
i think there is no need to store values first in a list and then add to a combobox.
it can be done directly to a combobox.
i have replace relative path a1 to a real one to let you understand easily.
foreach (string str in Directory.GetFiles(#"D:\"))
{
if (System.IO.Path.GetExtension(str).Contains("txt"))
{
this.Combobox_1.Items.Add(System.IO.Path.GetFileNameWithoutExtension(str));
}
}

Get single listView SelectedItem

I have the MultiSelect property of the listView set to false and I'm trying to get a single listViewItem. But the available property is SelectedItems. I've been using the following code...
foreach (ListViewItem item in listView1.SelectedItems)
{
//do something with item.text or whatever
}
Because I know there will only be one item selected. What is the correct way of doing this?
Usually SelectedItems returns either a collection, an array or an IQueryable.
Either way you can access items via the index as with an array:
String text = listView1.SelectedItems[0].Text;
By the way, you can save an item you want to look at into a variable, and check its structure in the locals after setting a breakpoint.
I do this like that:
if (listView1.SelectedItems.Count > 0)
{
var item = listView1.SelectedItems[0];
//rest of your logic
}
Sometimes using only the line below throws me an Exception,
String text = listView1.SelectedItems[0].Text;
so I use this code below:
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedIndices.Count <= 0)
{
return;
}
int intselectedindex = listView1.SelectedIndices[0];
if (intselectedindex >= 0)
{
String text = listView1.Items[intselectedindex].Text;
//do something
//MessageBox.Show(listView1.Items[intselectedindex].Text);
}
}
If its just a natty little app with one or two ListViews I normally just create a little helper property:
private ListViewItem SelectedItem { get { return (listView1.SelectedItems.Count > 0 ? listView1.SelectedItems[0] : null); } }
If I have loads, then move it out to a helper class:
internal static class ListViewEx
{
internal static ListViewItem GetSelectedItem(this ListView listView1)
{
return (listView1.SelectedItems.Count > 0 ? listView1.SelectedItems[0] : null);
}
}
so:
ListViewItem item = lstFixtures.GetSelectedItem();
The ListView interface is a bit rubbish so I normally find the helper class grows quite quickly.
For a shopping cart situation here's what I recommend. I'm gonna break it down into it's simplest form.
Assuming we start with this(a list view with 2 colums, 2 buttons, and a label):
First things first, removing the items, to do that we'll enter our remove button:
private void button2_Click(object sender, EventArgs e)
{
listView1.Items.Remove(listView1.SelectedItems[0]);
label1.Text = updateCartTotal().ToString();
}
Now the second line is updating our labels total using the next function i'll post to addup all the total of column 2 in the listview:
private decimal updateCartTotal()
{
decimal runningTotal = 0;
foreach(ListViewItem l in listView1.Items)
{
runningTotal += Convert.ToDecimal(l.SubItems[1].Text);
}
return runningTotal;
}
You don't have to use decimal like I did, you can use float or int if you don't have decimals. So let's break it down. We use a for loop to total all the items in the column 2(SubItems[1].Text). Add that to a decimal we declared prior to the foreach loop to keep a total. If you want to do tax you can do something like:
return runningTotal * 1.15;
or whatever your tax rate is.
Long and short of it, using this function you can retotal your listview by just calling the function. You can change the labels text like I demo'd prior if that's what you're after.
None of the answers above, at least to me, show how to actually handle determining whether you have 1 item or multiple, and how to actually get the values out of your items in a generic way that doesn't depend on there actually only being one item, or multiple, so I'm throwing my hat in the ring.
This is quite easily and generically done by checking your count to see that you have at least one item, then doing a foreach loop on the .SelectedItems, casting each item as a DataRowView:
if (listView1.SelectedItems.Count > 0)
{
foreach (DataRowView drv in listView1.SelectedItems)
{
string firstColumn = drv.Row[0] != null ? drv.Row[0].ToString() : String.Empty;
string secondColumn = drv.Row[1] != null ? drv.Row[1].ToString() : String.Empty;
// ... do something with these values before they are replaced
// by the next run of the loop that will get the next row
}
}
This will work, whether you have 1 item or many. It's funny that MSDN says to use ListView.SelectedListViewItemCollection to capture listView1.SelectedItems and iterate through that, but I found that this gave an error in my WPF app: The type name 'SelectedListViewItemCollection' does not exist in type 'ListView'.
foreach (ListViewItem itemRow in taskShowListView.Items)
{
if (itemRow.Items[0].Checked == true)
{
int taskId = Convert.ToInt32(itemRow.SubItems[0].Text);
string taskDate = itemRow.SubItems[1].ToString();
string taskDescription = itemRow.SubItems[2].ToString();
}
}
If you want to select single listview item no mouse click over it try this.
private void timeTable_listView_MouseUp(object sender, MouseEventArgs e)
{
Point mousePos = timeTable_listView.PointToClient(Control.MousePosition);
ListViewHitTestInfo hitTest = timeTable_listView.HitTest(mousePos);
try
{
int columnIndex = hitTest.Item.SubItems.IndexOf(hitTest.SubItem);
edit_textBox.Text = timeTable_listView.SelectedItems[0].SubItems[columnIndex].Text;
}
catch(Exception)
{
}
}
This works for single as well as multi selection list:
foreach (ListViewItem item in listView1.SelectedItems)
{
int index = item.Index;
//index is now zero based index of selected item
}
On mouse click, I would do it like this:
public static string GetSelectedItem(ListView list)
{
foreach (ListViewItem item in list.Items)
{
if (item.Selected)
return item.Text;
}
return null;
}

C# On_buttonClick, remove null contents from listbox

How do I setup a button click to remove only null contents from a listbox and keep the listbox populated.
Example:
Work
Files
here
Armor
Result (on_button_click,changes listbox):
Work
Files
here
Armor
Any help always appricated.
You need to loop backwards through the items in the ListBox and remove the items that you don't like.
For example:
for (int i = listBox.Items.Count - 1; i >= 0; i--) {
if (String.IsNullOrEmpty(listBox.Items[i] as String))
listBox.Items.RemoveAt(i);
}
The loop needs to be backwards because otherwise, all of the upcoming indices will move down.
Maybe something like this?
Whoops, as noted, you cannot iterate through a collection and modify it at the same time. Therefore, I present some Frankenstein code:
private void OnButtonClick(object sender, EventArgs e)
{
List<String> removeMe = new List<String>();
foreach(String x in listBox.Items)
{
if (String.IsNullOrEmpty(x))
{
removeMe.Add(x);
}
}
foreach(String x in removeMe)
{
listBox.Items.Remove(x);
}
}

Categories