I'm building an WinForms application which is going to be an adressbook. I'm stuck with a problem though. When I open the program and press on my load contacts button, it loads all that's written in the txt file. But if I create a new contact and press load again, the new contact doesn't show up. Is there any way to fix this?
Also, when I try to create new methods for example a Delete() method. It says "Items collection cannot be modified when the DataSource property is set." Any ideas why is crashes?
List<string> Load()
{
StreamReader read = new StreamReader(path);
string row = "";
while ((row = read.ReadLine()) != null)
{
adressbook.Add(row);
}
read.Close();
return adressbook; //Adressbook is my List<string> adressbook = new List<string> uptop.
}
private void button2_Click(object sender, EventArgs e)
{
List<string> list = Load();
listBox1.DataSource = list;
}
You have to set to null the DataSource before clearing and binding:
private void button2_Click(object sender, EventArgs e)
{
if(listBox1.DataSource != null)
{
listBox1.DataSource = null;
listBox1.Items.Clear();
}
List<string> list = Load();
listBox1.DataSource = list;
}
In your Load you must first clear the list
List<string> Load()
{
if (adressbook.Count != 0)
{
adressbook.Clear();
}
StreamReader read = new StreamReader(path);
string row = "";
while ((row = read.ReadLine()) != null)
{
adressbook.Add(row);
}
read.Close();
return adressbook; //Adressbook is my List<string> adressbook = new List<string> uptop.
}
Related
I launch the program, add some words to a listbox and try to remove it. If the selected item is last one, then it works fine, but if I select a word in the middle, then it removes the selected word. Then I loaded listbox again, and the last word disappeared somewhere. Any solutions?
public List<string> words = new List<string>();
public Form2()
{
InitializeComponent();
Load();
listBox1.DataSource = words;
}
public void Save()
{
const string sPath = "Data.txt";
System.IO.StreamWriter sw = new System.IO.StreamWriter(sPath);
foreach (string item in words)
{
sw.WriteLine(item);
}
sw.Close();
}
private void Load()
{
string line;
var file = new System.IO.StreamReader("Data.txt");
while ((line = file.ReadLine()) != null)
{
words.Add(line);
}
}
// This Part ???
private void Remove()
{
string contents = null;
List<string> itemAll = new List<string>();
foreach (string str in words)
{
itemAll.Add(str);
}
foreach (string lstitem in listBox1.SelectedItems)
{
itemAll.Remove(lstitem);
//File.AppendAllText(strFile + "Currently In.txt", strName + Environment.NewLine);
}
foreach (string s in itemAll)
{ contents += s + Environment.NewLine; }
System.IO.File.WriteAllText(#"Data.txt", contents);
}
private void button2_Click(object sender, EventArgs e)
{
// The Remove button was clicked.
int selectedIndex = listBox1.SelectedIndex;
try
{
// Remove the item in the List.
words.RemoveAt(selectedIndex);
}
catch
{
}
listBox1.DataSource = null;
listBox1.DataSource = words;
Remove();
}
Since words in your code is a global variable to all of your functions what happen is you are trying to remove items twice when you call this:
words.RemoveAt and itemAll.Remove
To prevent it, instead of calling Remove() method you can rename it as UpdateListBox() passing the words as argument like:
private void UpdateListBox(List<string> words)
{
string contents = null;
List<string> itemAll = new List<string>();
foreach (string str in words)
{
itemAll.Add(str);
}
}
Then you will have a separate method to save back:
private void Save(List<string> words)
{
StringBuilder contents = new StringBuilder();
foreach (string s in words)
{
contents.AppendLine(s);
}
System.IO.File.WriteAllText(#"Data.txt", contents);
}
Then you will call it like:
private void button2_Click(object sender, EventArgs e)
{
// The Remove button was clicked.
int selectedIndex = listBox1.SelectedIndex;
try
{
// Remove the item in the List.
words.RemoveAt(selectedIndex); //Remove item from words
UpdateListBox(words); //Update contents on GUI
Save(words); //Save on IO
}
catch
{
}
}
I just created it here and haven't tested it on my IDE, but you may have an idea how it is working.
I need 2 Dropdown list's in which the second drop down list is populated based on the firstone without using any javascript or ajax and in how many ways can we achieve this? i tried using methods but i couldn't bind it.
here is what i tried
public List <string> indiacities()
{
List<string> l2 = new List<string>();
l2.Add("hyderabad");
l2.Add("calcutta");
l2.Add("chennai");
return l2;
}
public List<string> usacities()
{
List<string> l1 = new List<string>();
l1.Add("newyork");
l1.Add("new jersy");
l1.Add("texas");
return l1;
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if(DropDownList1.SelectedValue=="0")
{
DropDownList2.DataSource=usacities();
DropDownList2.DataBind();
}
else if(DropDownList1.SelectedValue=="1")
{
DropDownList2.DataSource=indiacities();
DropDownList2.DataBind();
}
else{}
}
Here is an example, just to give you a general rough idea on how to assign a list as a datasource using your code.
List<string> UsaCities = new List<string>();
List<string> IndiaCities = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
UsaCities.Add("newyork");
UsaCities.Add("new jersy");
UsaCities.Add("texas");
IndiaCities.Add("hyderabad");
IndiaCities.Add("calcutta");
IndiaCities.Add("chennai");
DropDownList1.DataSource = UsaCities;
DropDownList1.DataBind();
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
if (DropDownList1.SelectedIndex == 0)
{
DropDownList2.DataSource = UsaCities;
DropDownList2.DataBind();
}
else if (DropDownList1.SelectedIndex == 1)
{
DropDownList2.DataSource = IndiaCities;
DropDownList2.DataBind();
}
}
i am new to asp.net and c# . i am using a session array to store list of values in to the session. but when i try to display the values using response.write method, it does not give the exact values in the session instead it says "System.Collections.ArrayList". the code i used to add values in the session is shown below.
protected void Page_Load(object sender, EventArgs e)
{
if (Session["Cart"] == null)
{
Session["Cart"] = new ArrayList();
}
else
{
ArrayList cart = (ArrayList)Session["Cart"];
}
}
protected void addtocart_Click(object sender, EventArgs e)
{
int dealid = Convert.ToInt32(Request.QueryString.Get("deal"));
ArrayList cart1 = new ArrayList();
cart1 = (ArrayList)Session["Cart"];
cart1.Add(dealid);
Session["Cart"] = cart1;
Response.Write(Session["Cart"].ToString());
}
}
can anyone help me to display the values that are stored inside the session. please..
You can't response.write(Session["Cart"].Tostring()) because Session["Cart"] is ArrayList. You have to loopthrough that arraylist before response.write like below:
protected void addtocart_Click(object sender, EventArgs e)
{
int dealid = Convert.ToInt32(Request.QueryString.Get("deal"));
ArrayList cart1 = new ArrayList();
cart1 = (ArrayList)Session["Cart"];
cart1.Add(dealid);
Session["Cart"] = cart1;
ArrayList cart2 = new ArrayList();
cart2 = (ArrayList)Session["Cart"];
foreach(var item in cart2 )
{
Response.WriteLine(item);
}
}
You need to make a loop for show all value in the session.
private ArrayList cart
{
get
{
if (Session["Cart"] == null)
{
Session["Cart"] = new ArrayList();
}
return (ArrayList)Session["Cart"];
}
set
{
Session["Cart"] = value;
}
}
protected void addtocart_Click(object sender, EventArgs e)
{
int dealid = Convert.ToInt32(Request.QueryString.Get("deal"));
cart.Add(dealid);
foreach (var item in cart)
{
Response.Write(item.ToString());
}
}
Because you placed ArrayList into Session. And then it returned it to you when you call Session["Cart"]. If you want to display all items from that list, then you need to iterate them like this:
protected void addtocart_Click(object sender, EventArgs e)
{
int dealid = Convert.ToInt32(Request.QueryString.Get("deal"));
ArrayList cart1 = new ArrayList();
cart1 = (ArrayList)Session["Cart"];
cart1.Add(dealid);
Session["Cart"] = cart1;
// iterate items in session
ArrayList cart = Session["Cart"] as ArrayList;
foreach(var item in cart)
{
Response.Write(item.ToString());
}
}
One more thing, that using
List<int>
is more useful and better that ArrayList, because you don't need to cast objects to needed type.
There is no need to assign cart1 back to session in Session["Cart"] = cart1;. To print dealid, you need to write something like Response.Write(Session["Cart"][0].ToString());
Iterate over arraylist and build the necessary string.
StringBuilder sb = new StringBuilder();
foreach(var obj in cart1)
{
sb.Append(obj.ToString())
}
Response.Write(sb.ToString());
There is a debug functionality inside Visual Studio. Set breakpoints in your code. Run your project and step through your code using F10 or F11. Click on a value and see it's content. More information? See this
For display arraylist item from the array you use below code:
foreach (var item in (ArrayList)Session["Cart"])
{
Response.Write(item);
}
hi guy i am trying to place my session in to a drop down, any help would be great.
at the moment it puts the data in to a label, i wish to put it into a dropdown with it adding a new string every time i click button without getting rid of the last
default page
protected void Button1_Click1(object sender, EventArgs e)
{
Session["Fruitname"] = TbxName.Text; // my session i have made
}
output page
protected void Page_Load(object sender, EventArgs e)
{
var fruitname = Session["Fruitname"] as String; // my session ive made
fruit.Text = fruitname; // session used in lable
}
Have Tried
var myFruits = Session["Fruitname"] as List<string>;
myFruits.Add(listbox1.Text);
but i get error when i try to run the program
Broken glass thanks for your help, it is still not doing what i need but its getting there.
var fruitname = Session["Fruitname"] as String; // my session ive made
fruit.Text = string.Join(",", fruitname); // session used in lable
this is what is working. i need a dropdown to display all the strings put into TbxName.Text; to output into fruit
Just use a List<string> instead of a string then.
var myFruits = Session["Fruitname"] as List<string>;
myFruits.Add(TbxName.Text);
Has been fixed using code found else where
button page code bellow
protected void Button1_Click1(object sender, EventArgs e)
{
// Session["Fruitname"] = TbxName.Text; // my session i have made
MyFruit = Session["Fruitname"] as List<string>;
//Create new, if null
if (MyFruit == null)
MyFruit = new List<string>();
MyFruit.Add(TbxName.Text);
Session["Fruitname"] = MyFruit;
{
public List<string> MyFruit { get; set; }
}
page where display
protected void Page_Load(object sender, EventArgs e)
{
MyFruit = Session["Fruitname"] as List<string>;
//Create new, if null
if (MyFruit == null)
MyFruit = new List<string>();
ListBox1.DataSource = MyFruit;
ListBox1.DataBind();
}
public List<string> MyFruit { get; set; }
}
I have following in Windows Forms .NET 3.5
It works fine for csv with records less than 10,000 but is slower for records above 30,000.
Input csv file can can any records between 1 - 1,00,000 records
Code currently used :
/// <summary>
/// This will import file to the collection object
/// </summary>
private bool ImportFile()
{
try
{
String fName;
String textLine = string.Empty;
String[] splitLine;
// clear the grid view
accountsDataGridView.Rows.Clear();
fName = openFileDialog1.FileName;
if (System.IO.File.Exists(fName))
{
System.IO.StreamReader objReader = new System.IO.StreamReader(fName);
do
{
textLine = objReader.ReadLine();
if (textLine != "")
{
splitLine = textLine.Split(',');
if (splitLine[0] != "" || splitLine[1] != "")
{
accountsDataGridView.Rows.Add(splitLine);
}
}
} while (objReader.Peek() != -1);
}
return true;
}
catch (Exception ex)
{
if (ex.Message.Contains("The process cannot access the file"))
{
MessageBox.Show("The file you are importing is open.", "Import Account", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
MessageBox.Show(ex.Message);
}
return false;
}
}
Sample Input file :
18906,Y
18908,Y
18909,Y
18910,Y
18912,N
18913,N
Need some advice on optimizing this code for fast reads & view in grid.
List<string[]> rows = File.ReadAllLines("Path").Select(x => x.Split(',')).ToList();
DataTable dt = new DataTable();
dt.Columns.Add("1");
dt.Columns.Add("2");
rows.ForEach(x => {
dt.Rows.Add(x);
});
dgv.DataSource = dt;
Try that, I suspected that you have some form of column names in the datagrid for now I just made them 1 and 2.
To filter as per your original code use:
List<string[]> rows = File.ReadAllines("Path").Select(x => x.Split(',')).Where(x => x[0] != "" && x[1] != "").ToList();
To get your columns from the DataGridView
dt.Columns.AddRange(dgv.Columns.Cast<DataGridViewColumn>().Select(x => new DataColumn(x.Name)).ToArray());
There isn't much to optimize in regards to speed, but following is much more readable. If it is too slow, it probably isn't the method reading the file, but your WinForm that needs to display >30k records.
accountsDataGridView.Rows.Clear();
using (FileStream file = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096))
using (StreamReader reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
var fields = reader.ReadLine().Split(',');
if (fields.Length == 2 && (fields[0] != "" || fields[1] != ""))
{
accountsDataGridView.Rows.Add(fields);
}
}
}
You can try to use SuspendLayout() and ResumeLayout() Methods.
From MSDN Documentation
"The SuspendLayout and ResumeLayout methods are used in tandem to suppress multiple Layout events while you adjust multiple attributes of the control. For example, you would typically call the SuspendLayout method, then set the Size, Location, Anchor, or Dock properties of the control, and then call the ResumeLayout method to enable the changes to take effect."
accountsDataGridView.SuspendLayout();
accountsDataGridView.Rows.Clear();
// .....
// in the end after you finished populating your grid call
accountsDataGridView.ResumeLayout();
Instead of putting the data directly into the grid you should take a look at the VirtualMode of the DataGridView.
In your code you're doing two things at one time (read the file, fill the grid), which leads to your freezed gui. Instead you should put the grid into the virtual mode and read the file within a BackgroundWorker into a list which holds the data for the grid. The background worker can after each line read update the virtual size of the grid, which allows to already see the data while the grid is loading. By using this approach you'll getting a smooth working grid.
Below you'll find an example which just needs to be filled into a form that uses a DataGridView with two text columns, a BackgroundWorker and a Button:
public partial class FormDemo : Form
{
private List<Element> _Elements;
public FormDemo()
{
InitializeComponent();
_Elements = new List<Element>();
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.ReadOnly = true;
dataGridView.VirtualMode = true;
dataGridView.CellValueNeeded += OnDataGridViewCellValueNeeded;
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork += OnBackgroundWorkerDoWork;
backgroundWorker.ProgressChanged += OnBackgroundWorkerProgressChanged;
backgroundWorker.RunWorkerCompleted += OnBackgroundWorkerRunWorkerCompleted;
}
private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
var filename = (string)e.Argument;
using (var reader = new StreamReader(filename))
{
string line = null;
while ((line = reader.ReadLine()) != null)
{
var parts = line.Split(',');
if (parts.Length >= 2)
{
var element = new Element() { Number = parts[0], Available = parts[1] };
_Elements.Add(element);
}
if (_Elements.Count % 100 == 0)
{
backgroundWorker.ReportProgress(0);
}
}
}
}
private void OnBackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{
dataGridView.RowCount = _Elements.Count;
}
private void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
dataGridView.RowCount = _Elements.Count;
button.Enabled = true;
}
private void OnButtonLoadClick(object sender, System.EventArgs e)
{
if (!backgroundWorker.IsBusy
&& DialogResult.OK == openFileDialog.ShowDialog())
{
button.Enabled = false;
backgroundWorker.RunWorkerAsync(openFileDialog.FileName);
}
}
private void OnDataGridViewCellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
var element = _Elements[e.RowIndex];
switch (e.ColumnIndex)
{
case 0:
e.Value = element.Number;
break;
case 1:
e.Value = element.Available;
break;
}
}
private class Element
{
public string Available { get; set; }
public string Number { get; set; }
}
}