简体   繁体   中英

Visual C# program saves only last index to XML file

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.

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

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.

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();
    }
}

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..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM