Reputation: 11
I'm fairly new to C# development, currently building a booking application for a marina.
(Have searched previous questions but haven't been successful in locating specifically what I'm seeking)
Use case:
I have configured the program to create an XML file for the form input, However, I can not figure out how to create a separate XML file for each entry.
Currently, each time I enter the form data, it overwrites the previous XML data in the file.
Any solutions as to how to create separate/additional XML files as per above are much appreciated.
First time posting here, so apologies if I've omitted any necessary info.
Code is as follows:
// Save XML.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.IO;
namespace Popeye_Booking_application
{
public class SaveXml
{
public static void SaveData(object obj, string filename)
{
XmlSerializer sr = new XmlSerializer(obj.GetType());
TextWriter writer = new StreamWriter(filename);
sr.Serialize(writer, obj);
writer.Close();
}
}
}
// Information.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Popeye_Booking_application
{
public class Information
{
private string data1;
private string data2;
private string data3;
private string data4;
private string data5;
private string data6;
private string data7;
public string Data1
{
get { return data1; }
set { data1 = value; }
}
public string Data2
{
get { return data2; }
set { data2 = value; }
}
public string Data3
{
get { return data3; }
set { data3 = value; }
}
public string Data4
{
get { return data4; }
set { data4 = value; }
}
public string Data5
{
get { return data5; }
set { data5 = value; }
}
public string Data6
{
get { return data6; }
set { data6 = value; }
}
public string Data7
{
get { return data7; }
set { data7 = value; }
}
}
}
// Form.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Popeye_Booking_application
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonCreate_Click(object sender, EventArgs e)
{
try
{
Information info = new Information();
info.Data1 = textBoxData1.Text;
info.Data2 = textBoxData2.Text;
info.Data3 = textBoxData3.Text;
info.Data4 = textBoxData4.Text;
info.Data5 = textBoxData5.Text;
info.Data6 = textBoxData6.Text;
info.Data7 = textBoxData7.Text;
SaveXml.SaveData(info, "data.xml");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label4_Click(object sender, EventArgs e)
{
}
private void label10_Click(object sender, EventArgs e)
{
}
private void label7_Click(object sender, EventArgs e)
{
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
}
}
Thanks in advance,
Upvotes: 1
Views: 1200
Reputation: 23732
However, I can not figure out how to create a separate XML file for each entry.
You need for each entry a specific distinguishable id or name. So I would suggest to make an extra property in the Class Information
for it:
public class Information
{
public string Name { get; set; }
this would also help you to manage the 3. point
3.Return data to gridView when searched by name via form. (e.g client lookup)
You would need an extra TextBox
for the Name entry:
Information info = new Information();
info.Name= textBoxName.Text;
And if it does not already exist then save it: string filename = info.Name + ".XML"
if (!System.IO.File.Exists(filename))
{
SaveXml.SaveData(info, filename);
}
else
{
// notify that name is imabiguous
}
When Loading you could search for that file.
Another possibility would be to make an extra class with only 1 property: a List<Information> InfoList
. That can be saved in one file with all the information entries. This can then be bound easily to a DataGridView
and also can be search easily for specific items using the Name
property.
EDIT:
Here is a little run through that you asked for:
The basic structure of your Information
class remains the same:
public class Information
{
public string Name { get; set; }
public string Data1 { get; set; }
public string Data2 { get; set; }
// and so on... you get the drift
}
You need a container class for all those infos. So that you can use only file to save them all ;). This class can then also get the methods to save and load:
public class InformationSaveFile
{ // A list to safe all info entries
public List<Information> InformationList { get; set; }
public InformationSaveFile()
{
InformationList = new List<Information>();
}
// you method to save data
public static void SaveData(object obj, string filename)
{
XmlSerializer sr = new XmlSerializer(obj.GetType());
TextWriter writer = new StreamWriter(filename);
sr.Serialize(writer, obj);
writer.Close();
}
// a method to Load the Data
public static InformationSaveFile LoadData(string FileName)
{
using (var stream = File.OpenRead(FileName)) // File ist aus dem Namensraum System.IO
{
var serializer = new XmlSerializer(typeof(InformationSaveFile));
InformationSaveFile w = serializer.Deserialize(stream) as InformationSaveFile;
return w;
}
}
}
In your form you would need an Instance of the container class:
// public is not necessary here
public InformationSaveFile InfoSaveFile { get; set; }
now to add data you would use the InformationList
, and to save the data the SaveData
method like this:
private void buttonCreate_Click(object sender, EventArgs e)
{
//Adding of Info Items:
Information info = new Information();
info.Name = "Specific Name";
info.Data1 = textBoxData1.Text;
// and so on...
InfoSaveFile.InformationList.Add(info);
InformationSaveFile.SaveData(InfoSaveFile, "YourFileName.XML");
For loading the data you would now need only the same filename and all your data that you added to the InformationList
and saved will be at your disposal:
InfoSaveFile = InformationSaveFile.LoadData("YourFileName.XML");
Now you can use the List to filter the data for the entry that you need:
// Search for certain names:
List<Information> infoList = InfoSaveFile.InformationList.FindAll(x => x.Name == "Search Name");
// OR looking with contains (makes the search broader)
List<Information> infoList_broad = InfoSaveFile.InformationList.FindAll(x => x.Name.Contains("Search Name"));
Now that became a very long answer. I hope you can follow that run through, and the answer helps. If not just drop me a comment.
Upvotes: 0
Reputation: 34421
Use a DataTable. It is easier to read and write. Also add a DataGridView to the form
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
namespace Popeye_Booking_application
{
public partial class Form1 : Form
{
const string FILENAME = @"c:\temp\test.xml";
DataTable dt = new DataTable();
public Form1()
{
InitializeComponent();
if (File.Exists(FILENAME))
{
dt.ReadXml(FILENAME);
dataGridView1.DataSource = dt;
}
else
{
dt.TableName = "Data";
dt.Columns.Add("Data1",typeof(string));
dt.Columns.Add("Data2", typeof(string));
dt.Columns.Add("Data3", typeof(string));
dt.Columns.Add("Data4", typeof(string));
dt.Columns.Add("Data5", typeof(string));
dt.Columns.Add("Data6", typeof(string));
dt.Columns.Add("Data7", typeof(string));
SaveXml.SaveData(dt, FILENAME);
}
}
private void buttonCreate_Click(object sender, EventArgs e)
{
try
{
Information info = new Information();
info.Data1 = textBoxData1.Text;
info.Data2 = textBoxData2.Text;
info.Data3 = textBoxData3.Text;
info.Data4 = textBoxData4.Text;
info.Data5 = textBoxData5.Text;
info.Data6 = textBoxData6.Text;
info.Data7 = textBoxData7.Text;
dt.Rows.Add(new object[] {
info.Data1,
info.Data2,
info.Data3,
info.Data4,
info.Data5,
info.Data6,
info.Data7
});
dt.AcceptChanges();
dataGridView1.DataSource = null;
dataGridView1.DataSource = dt;
SaveXml.SaveData(dt, FILENAME);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void label1_Click(object sender, EventArgs e)
{
}
private void label4_Click(object sender, EventArgs e)
{
}
private void label10_Click(object sender, EventArgs e)
{
}
private void label7_Click(object sender, EventArgs e)
{
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
}
public class SaveXml
{
public static void SaveData(DataTable dt, string filename)
{
dt.WriteXml(filename, XmlWriteMode.WriteSchema);
}
}
public class Information
{
private string data1;
private string data2;
private string data3;
private string data4;
private string data5;
private string data6;
private string data7;
public string Data1
{
get { return data1; }
set { data1 = value; }
}
public string Data2
{
get { return data2; }
set { data2 = value; }
}
public string Data3
{
get { return data3; }
set { data3 = value; }
}
public string Data4
{
get { return data4; }
set { data4 = value; }
}
public string Data5
{
get { return data5; }
set { data5 = value; }
}
public string Data6
{
get { return data6; }
set { data6 = value; }
}
public string Data7
{
get { return data7; }
set { data7 = value; }
}
}
}
Upvotes: 1
Reputation: 2163
Use XDocument class to create an object for each entry and then use Save method inside it, check this link : https://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument(v=vs.110).aspx
Upvotes: 0