Reputation: 13
private void button1_Click(object sender, EventArgs e) //add data to listBox
{
if (String.IsNullOrWhiteSpace(textBox1.Text) || String.IsNullOrWhiteSpace(textBox2.Text))
{
MessageBox.Show("Proszę uzupełnić wszystkie pola, aby wprowadzić dane", "Błąd!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
listBox1.Items.Add(textBox4.Text + " " + textBox1.Text + " " + textBox2.Text);
listBox1.DisplayMember = textBox4.Text;
}
private void button2_Click(object sender, EventArgs e) //delete data from listbox
{
if(listBox1.SelectedIndex == -1)
{
MessageBox.Show("Proszę zaznaczyć pozycję by usunąć", "Błąd!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
listBox1.Items.Remove(listBox1.SelectedItem);
}
private void button3_Click(object sender, EventArgs e) //save to XML button
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.TableName = "Tabela";
dt.Columns.Add("Name");
dt.Columns.Add("Surname");
dt.Columns.Add("PESEL");
dt.Columns.Add("Room");
ds.Tables.Add(dt);
foreach (string item in listBox1.Items)
{
DataRow dr = ds.Tables["Tabela"].NewRow();
dr["Name"] = textBox1.Text;
dr["Surname"] = textBox2.Text;
dr["PESEL"] = textBox3.Text;
dr["Room"] = textBox4.Text;
ds.Tables["Tabela"].Rows.Add(dr);
}
ds.WriteXml("D:\\data.xml");
}
private void button4_Click(object sender, EventArgs e) //read from XML button
{
DataSet ds = new DataSet();
ds.ReadXml("D:\\data.xml");
foreach (DataRow item in ds.Tables["Tabela"].Rows)
{
listBox1.Items.Add(string.Format("{0} {1} {2}", item["Room"], item["Name"], item["Surname"]));
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DataSet ds = new DataSet();
ds.ReadXml("D:\\data.xml");
foreach (DataRow item in ds.Tables["Tabela"].Rows)
{
textBox1.Text = item["Name"].ToString();
textBox2.Text = item["Surname"].ToString();
textBox3.Text = item["PESEL"].ToString();
textBox4.Text = item["Room"].ToString();
}
}
I have a problem while saving and reading XML file. When I will add some data to listBox from textBoxes is saves only last index I added, but multiple times.
Example:
<Tabela>
<Name>John</Name>
<Surname>Johnson</Surname>
<PESEL>123465789</PESEL>
<Room>21</Room>
</Tabela>
<Tabela>
<Name>John</Name>
<Surname>Johnson</Surname>
<PESEL>123465789</PESEL>
<Room>21</Room>
</Tabela>
<Tabela>
<Name>John</Name>
<Surname>Johnson</Surname>
<PESEL>123465789</PESEL>
<Room>21</Room>
</Tabela>
And when I load data from XML the listBox works fine, but when I selected one index from this list in my textBoxes appears only last index, not that I have clicked.
Upvotes: 1
Views: 100
Reputation: 2128
You are using a very bad approach with a listbox control that represents your main business entity. This is very bad...
In fact in order to make to work your solution, you should save into xml file everytime you add a new item data in the expected text boxes and the avoid to loop the listbox items when saving...
Then it is wrong also the method to display the details of your selected item when occurs the SelectedIndexChanged
event, because you don't point to the correct listbox item selcted, but to the last saved item in the file everytime you select a new item in your listbox.
So, a better approach could be declare a class that will be your entity and a Collection of this class that will be the datasource of your listbox:
public class Booking{
string Name;
string Surname;
string PESEL; //your key? remember to manage duplicates if you insert manually (better if it were generated automatically as unique data (Guid))
string Room;
}
System.Collections.Generic.List<Booking> bookings; //instantiate in Form constructor method
then, your UI controls event handlers will manage this objects in order to do your operations, and so:
When you add a new item:
if (String.IsNullOrWhiteSpace(textBox1.Text) || String.IsNullOrWhiteSpace(textBox2.Text))
{
MessageBox.Show("Proszę uzupełnić wszystkie pola, aby wprowadzić dane", "Błąd!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
bookings.Add(new Booking{
Name = textBox1.Text,
Surname = textBox2.Text,
PESEL = textBox3.Text,
Room = textBox4.Text
});
listBox.DataSource = null;
listBox.DataSource = bookings; //use the datasource property
listBox.DisplayMember = "Room";
listBox.ValueMember = "PESEL";
When you delete one item:
if (listBox.SelectedIndex == -1) {
MessageBox.Show("Proszę zaznaczyć pozycję by usunąć", "Błąd!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
bookings.Remove(bookings.Find(c => c.PESEL == listBox.SelectedValue as string));
listBox.DataSource = null;
listBox.DataSource = bookings; //use the datasource property
listBox.DisplayMember = "Room";
listBox.ValueMember = "PESEL";
When you save your items:
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.TableName = "Tabela";
dt.Columns.Add("Name");
dt.Columns.Add("Surname");
dt.Columns.Add("PESEL");
dt.Columns.Add("Room");
ds.Tables.Add(dt);
foreach (Booking item in bookings)
{
DataRow dr = ds.Tables["Tabela"].NewRow();
dr["Name"] = item.Name;
dr["Surname"] = item.Surname;
dr["PESEL"] = item.PESEL;
dr["Room"] = item.Room;
ds.Tables["Tabela"].Rows.Add(dr);
}
ds.WriteXml("D:\\data.xml");
When you load from file
//attention to eventual new records appended to the list you may lose them
DataSet ds = new DataSet();
ds.ReadXml("D:\\data.xml");
bookings.Clear(); //<<== avoids dirty loading (duplicates)
foreach (DataRow item in ds.Tables["Tabela"].Rows) {
bookings.Add(new Booking() {
Name = item["Name"].ToString(),
Surname = item["Surname"].ToString(),
PESEL = item["PESEL"].ToString(),
Room = item["Room"].ToString()
});
}
listBox.DataSource = null;
listBox.DataSource = bookings; //use the datasource property
listBox.DisplayMember = "Room";
listBox.ValueMember = "PESEL";
When you want display details of a selcted listbox item:
Booking booking = bookings.Find(c => c.PESEL == listBox.SelectedValue as string);
if (booking == null) return;
textBox1.Text = booking.Name;
textBox2.Text = booking.Surname;
textBox3.Text = booking.PESEL;
textBox4.Text = booking.Room;
You may refactor the repetitive statements about listbox refreshing..
Upvotes: 0
Reputation: 7115
change listBox1_SelectedIndexChanged method in that way that the selected listbox value is used as filter for your table, something like this:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DataSet ds = new DataSet();
ds.ReadXml("D:\\data.xml");
//split selected item by spaces
var values = listBox1.SelectedItem.ToString().Split(' ');
var selectedRow = ds.Tables["Tabela"].AsEnumerable()
.Where
(r => r["Room"].ToString() == values[0] &&
r["Name"].ToString() == values[1] &&
r["Surname"].ToString() == values[2]).FirstOrDefault();
if (selectedRow != null)
{
textBox1.Text = selectedRow["Name"].ToString();
textBox2.Text = selectedRow["Surname"].ToString();
textBox3.Text = selectedRow["PESEL"].ToString();
textBox4.Text = selectedRow["Room"].ToString();
}
}
Upvotes: 0
Reputation: 11501
foreach (string item in listBox1.Items)
{
DataRow dr = ds.Tables["Tabela"].NewRow();
dr["Name"] = textBox1.Text;
dr["Surname"] = textBox2.Text;
dr["PESEL"] = textBox3.Text;
dr["Room"] = textBox4.Text;
ds.Tables["Tabela"].Rows.Add(dr);
}
I'm not sure what do you want to do but you would probably want to change something like reading and writing from a list or something.
If you tell us the technology that you are using (asp.net, wpf, etc.), we probably can help you out.
Upvotes: 1
Reputation: 17868
In your code you have
dr["Name"] = textBox1.Text;
dr["Surname"] = textBox2.Text;
dr["PESEL"] = textBox3.Text;
dr["Room"] = textBox4.Text;
For each itteration in the listbox items. As the textboxes wont be changing it will indeed add one for each item in your listbox.
Im thinking you needed to do something with item, in your for loop, not the text boxes
Upvotes: 2