So far I've followed the textbook route of adding adding data to an XML file; first, I created a class:
[Serializable]
public class Note
{
public string Notes { get; set; }
}
And then done this:
private void addButton_Click(object sender, RoutedEventArgs e)
{
string stringToAdd = textBox.Text;
Notes.Add(stringToAdd);
using (StringWriter myStringWirter = new StringWriter())
{
XmlSerializer myXML = new XmlSerializer(typeof(Note));
Note myNote = new Note();
myNote.Notes = stringToAdd;
myXML.Serialize(myStringWirter, myNote);
using (StreamWriter myStreamWriter = new StreamWriter("Notes.xml"))
{
myStreamWriter.Write(myStringWirter);
}
}
But Notes.xml doesn't get updated. Why?
Edit. Now it works. Just by using List instead of Note.
Related
I've used a button with this method to deserialize a ObservableCollection but after i can't no more add a object to my list.
private async void RecoveryList_Click(object sender, RoutedEventArgs e)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("List.xml");
DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<ProductClass>));
using (Stream stream = await file.OpenStreamForReadAsync())
{
ObservableCollection<ProductClass> Products = serializer.ReadObject(stream) as ObservableCollection<ProductClass>;
ListView1.ItemsSource = Products;
}
}
And to serialize
private async void ButtonSave_Click(object sender, RoutedEventArgs e)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<ProductClass>));
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("List.xml", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await file.OpenStreamForWriteAsync())
{
serializer.WriteObject(stream, Products);
ListView1.ItemsSource = Products;
}
}
To add product I've used this
private async void ButtonAdd_Click(object sender, RoutedEventArgs e)
{
Products.Add(new ProductClass{ Prodotti = TexBoxInputProducts.Text });
}
My ObservableCollection is
public ObservableCollection<ProductClass> Products;
My class is
namespace AppSpesaPhone.Models
{
public class ProductClass
{
public string Prodotti { get; set; }
}
}
How can i add some "Product" to my list?
You have a public ObservableCollection<ProductClass> field named Products in your class, but in your RecoveryList_Click method, you use a new ObservableCollection also named Products to retrieve the deserialized list and set it as ListView's ItemsSource. Although they are the same name, but they are not the same object. So you can't add new item to the ListView.
To fix this issue, you can remove the declaration of new Products in RecoveryList_Click method like following and make sure in all methods, you are operating the same object.
private async void RecoveryList_Click(object sender, RoutedEventArgs e)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("List.xml");
DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<ProductClass>));
using (Stream stream = await file.OpenStreamForReadAsync())
{
Products = serializer.ReadObject(stream) as ObservableCollection<ProductClass>;
ListView1.ItemsSource = Products;
}
}
so here it is my code.
public List<Serialization> list = null;
private void UCAPIn_Load(object sender, EventArgs e)
{
list = new List<Serialization>();
if (File.Exists("date.XML"))
{
var doc = XDocument.Load("data.XML");
foreach (XElement element in doc.Descendants("Serialization"))
{
list.Add(new Serialization()
{ ID = element.Element("ID").Value,
APIKEY = element.Element("APIKEY").Value,
VCODE = element.Element("VCODE").Value });
}
}
}
public void button1_Click(object sender, EventArgs e)
{
{
try
{
Serialization info = new Serialization();
info.APIKEY = txtAPI.Text;
info.VCODE = txtVerC.Text;
info.ID = Guid.NewGuid().ToString();
list.Add(info);
Serialization.SaveData(list, "data.XML");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
private void whatIsThisToolStripMenuItem_Click(object sender, EventArgs e)
{
}
// end of UCAPIn
public class Serialization
{
private string id;
private string APIkey;
private string VCode;
public string ID
{
get { return id; }
set { id = value; }
}
public string APIKEY
{
get { return APIkey; }
set { APIkey = value; }
}
public string VCODE
{
get { return VCode; }
set { VCode = value; }
}
public static void SaveData(List<Serialization> list, string Filename)
{
File.Delete(Filename);
XmlSerializer sr = new XmlSerializer(list.GetType());
TextWriter writer = new StreamWriter(Filename, true);
sr.Serialize(writer, list);
writer.Close();
}
}
it create my XML and adds to it (multiple entries) but when i close the program and reopen it add some more data in the older data is gone, overwritten by the new.
Can anyone help me with this one?
(thanks in advance)
XML Sample (when File.Delete(Filename); is removed.:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSerialization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Serialization>
<ID>f2310827-93d0-42aa-9bfe-32624ee5f97b</ID>
<APIKEY>1234</APIKEY>
<VCODE>1234</VCODE>
</Serialization>
</ArrayOfSerialization>
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSerialization xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Serialization>
<ID>df354c83-1ae2-4cfc-b802-c9682f24f3f6</ID>
<APIKEY>123</APIKEY>
<VCODE>123</VCODE>
</Serialization>
</ArrayOfSerialization>
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSerialization xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Serialization>
<ID>df354c83-1ae2-4cfc-b802-c9682f24f3f6</ID>
<APIKEY>123</APIKEY>
<VCODE>123</VCODE>
</Serialization>
<Serialization>
<ID>a8f6737e-6c08-4e7a-b041-c16b502d4a60</ID>
<APIKEY>1234</APIKEY>
<VCODE>1234</VCODE>
</Serialization>
</ArrayOfSerialization>
Hope this sample code helps you.
I'm using the same property class that you are using "Serialization"
For Deserialization use this method:
public List<Serialization> XMLDeserialize()
{
XmlSerializer deserializer = new XmlSerializer(typeof(List<Serialization>));
TextReader reader = new StreamReader(xmlPath);
var XMLDeserialize = (List<Serialization>) deserializer.Deserialize(reader);
reader.Dispose();
return XMLDeserialize;
}
To update the xml file use this function:
public void UpdateXMLSerialize(List<Serialization> objXmlData)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Serialization>));
using (TextWriter writer = new StreamWriter(xmlPath))
{
serializer.Serialize(writer, objXmlData);
}
}
To add new data in xml on click event:
private void Add_Click(object sender, EventArgs e)
{
List<Serialization> list = new List<Serialization>();
if (File.Exists(xmlPath))
{
list = XMLDeserialize();
Serialization obj = new Serialization() { ID = "NewData", APIKEY = "NewAPIKey", VCODE = "NewVCode" };
list.Add(obj);
UpdateXMLSerialize(list);
}
}
I'm trying to make an application that allows people to register their information so that employers could read them and contact them.
The problem is whenever I try to deserialize the information, I either get one object only, or the program throw an exception.
private void button1_Click(object sender, EventArgs e)
{
FileStream sw = new FileStream("Applicants.xml",FileMode.Append,FileAccess.Write,FileShare.None);
XmlSerializer xs = new XmlSerializer(typeof(Class1), new XmlRootAttribute("Applist"));
Class1 cc = new Class1();
cc.name = textBox1.Text;
cc.age = textBox2.Text;
cc.degree = textBox3.Text;
cc.salary = textBox4.Text;
cc.no = textBox5.Text;
c.Add(cc);
xs.Serialize(sw,cc);
this.Hide();
}
What should I do to serialize and deserialize all the objects created ?
class1 :
public class Class1
{
public String name;
public String age;
public String degree;
public String no;
public String salary;
}
deserialization code :
private void linkLabel1_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e)
{
List<Class1> c2 = new List<Class1>();
XmlSerializer xml = new XmlSerializer(typeof(List<Class1>));
FileStream fs = new FileStream("Applicants.xml",FileMode.Open);
c2 = (List<Class1>)xml.Deserialize(fs);
label3.Text = ; //don't know what t write here
}
If you want to serialize the list, you have to create the Serializer for the type of List<Class1>.
XmlSerializer xs = new XmlSerializer(typeof(List<Class1>), new XmlRootAttribute("Applist"));
And then serialize the actual list instead of cc.
xs.Serialize(sw,c);
I have a class with different methods from a Windows Form. In my test code, I used this to create a new OpenXML Document:
using (WordprocessingDocument package = WordprocessingDocument.Create(docName, WordprocessingDocumentType.Document))
But this seems not working on multiple methods. How can I fix it? It won't work without the using, so after a bit of research I found out that this class was IDisposable.
But I have 2 needs right now:
1) If the file exists, the document has to open instead of creating a new one.
2) The docName, which contains the path to the file that he's going to save, has to be reachable end used in the block as seen above.
Is there a way to do this?
This is my code right now:
using System;
using System.IO;
using System.Windows.Forms;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace WordExample
{
public partial class Word : Form
{
private string _docName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\xxx2.docx";
private WordprocessingDocument _package;
private Document _doc;
private Body _body;
public Word()
{
InitializeComponent();
/*if (File.Exists(_docName))
{
_package = WordprocessingDocument.Open(_docName, false);
_doc = _package.MainDocumentPart.Document;
_body = _doc.Body;
}
else
{
_package = WordprocessingDocument.Create(_docName, WordprocessingDocumentType.Document);
_package.AddMainDocumentPart();
_doc = _package.MainDocumentPart.Document;
_body = new Body();
}*/
_package = WordprocessingDocument.Create(_docName, WordprocessingDocumentType.Document);
_package.AddMainDocumentPart();
_doc = new Document();
_body = new Body();
}
private void Word_Load(object sender, EventArgs e)
{
}
private void btnAddParagraph_Click(object sender, EventArgs e)
{
/*Paragraph p = new Paragraph();
Text t = new Text(txtTekstParagraaf.Text);
Run r = new Run();
RunProperties rPr = new RunProperties();
if (chkBold.Checked)
{
Bold b = new Bold();
rPr.Append(b);
}
if (chkItalic.Checked)
{
Italic b = new Italic();
rPr.Append(b);
}
if (chkUnderline.Checked)
{
Underline b = new Underline();
rPr.Append(b);
}
//RunProperties
//r.PrependChild<RunProperties>(rPr);
r.PrependChild(rPr);
r.AppendChild(t);
p.AppendChild(r);
_body.AppendChild(p);*/
Save();
}
private void Save()
{
_doc.AppendChild(_body);
_package.MainDocumentPart.Document = _doc;
// Save changes to the main document part.
_package.MainDocumentPart.Document.Save();
}
}
}
But this code generates an error when trying to open the created document afterwards AND when I try to open an document instead of creating one.
You can try using trenary operator here:
using (WordprocessingDocument package = File.Exists(docName) ?
WordprocessingDocument.Create(docName, WordprocessingDocumentType.Document) :
WordprocessingDocument.Open(docName, WordprocessingDocumentType.Document)) {
...
}
If the file exists, the document has to open instead of creating a new one.
So why don't you use an if statement?
if(File.Exists(docName))
{
using(var package = ..) // open file
{
...
}
}
else
{
using(var package = ..) // create file
{
...
}
}
You are not forced to instantiate variable directly in using statement. You can move creation to separate method:
private WordprocessingDocument GetPackage(string docName)
{
var docType = WordprocessingDocumentType.Document;
if (File.Exists(docName))
return WordprocessingDocument.Open(docName, docType);
return WordprocessingDocument.Create(docName, docType);
}
Now your code will look like:
using(var package = GetPackage(docName))
{
// ...
}
UPDATE: If you want to reuse disposable dependency in all methods of class (as you stated in comments) you should implement IDisposale by class which holds disposable dependency, and dispose that dependency when you are disposing class:
public class Foo : IDisposable
{
private readonly WordprocessingDocument _package;
public Foo()
{
_package = GetPackage(docName); // implemented as above
}
public void Method1()
{
// use _package without `using` block
}
public void Method2()
{
// use _package without `using` block
}
public void Dispose()
{
if (_package != null)
_package.Dispose();
}
}
Then wrap instance of Foo into using block:
using(var foo = new Foo()) // _package created here
{
foo.Method1(); // same _package instance used by both methods
foo.Method2();
} // _package will be disposed here
In writing a program where I need to serialize an AppSettings object which consists of several properties including one that will be used to store a last used filename, I have found that the FileName property is placed into my object (by assignment) but it does not serialize to the xml file. No exceptions are thrown and no data is written.
But conversely, if I programmtically modify the object
tc.TheDataFile = "c:\\Documents And Settings\\SomeUser\\Sample\\a test file.txt";
instead of
tc.TheDataFile = theDialog.FileName;
That will work. Can someone please provide some insight with regard to what I am missing?
Here is a simple version of the program that is directly related to the problem.
The test class which will theoretically hold the AppSettings ---
[Serializable()]
public class TestClass
{
private string m_TheDataFile;
private bool m_UseLastKnownDataFile = true;
public bool UseLastKnownDataFile
{
get
{
return m_UseLastKnownDataFile;
}
set
{
m_UseLastKnownDataFile = value;
}
}
public string TheDataFile
{
get
{
return m_TheDataFile;
}
set
{
m_TheDataFile = value;
}
}
}
public class TestClassHelper
{
public static TestClass Load()
{
XmlSerializer serializer = new XmlSerializer(typeof(TestClass));
TestClass retVal;
TextReader reader = null;
bool fileNotFound = false; ;
try
{
reader = new StreamReader("TestClassConfig.xml");
}
catch (FileNotFoundException)
{
fileNotFound = true;
}
if (fileNotFound)
{
retVal = new TestClass();
}
else
{
retVal = (TestClass)serializer.Deserialize(reader);
reader.Close();
}
return retVal;
}
public static void Save(TestClass settings)
{
XmlSerializer serializer = new XmlSerializer(typeof(TestClass));
TextWriter writer = new StreamWriter("TestClassConfig.xml");
serializer.Serialize(writer, settings);
writer.Close();
}
}
And here is the form which will prompt the user for a filename. In this test, there is a form with one button.
public partial class Form1 : Form
{
TestClass tc = null;
public Form1()
{
InitializeComponent();
tc = TestClassHelper.Load();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog theDialog = new OpenFileDialog();
string fileName = string.Empty;
theDialog.CheckFileExists = true;
theDialog.CheckPathExists = true;
theDialog.Multiselect = false;
theDialog.FileName = string.Empty;
if (theDialog.ShowDialog() == DialogResult.OK)
{
tc.TheDataFile = theDialog.FileName;
}
else
{
tc.TheDataFile = string.Empty;
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
TestClassHelper.Save(tc);
}
}
Edit To Add:
I'm using Microsoft Visual Studio 2005 Team Edition w/Dot Net 2.0.50727 SP1, with no options to upgrade the development environment.
Solution
I'm not exactly sure why this happens, but the OpenFileDialog control must change the current operating directory of the program. When the object is deserialized to the xml file, it no longer writes where it originally opened. Rather it is created in the new directory.
I corrected the problem by making the XML read and write location more specific.
The problem is that you are setting tc.TheDataFile = fileName; after the if block, but you never assign anything to fileName except when you initialize it to string.Empty. One fix would be:
if (theDialog.ShowDialog() == DialogResult.OK)
{
fileName = theDialog.FileName;
}
// record last used data file
tc.TheDataFile = fileName;
or just
if (theDialog.ShowDialog() == DialogResult.OK)
{
tc.TheDataFile = theDialog.FileName;
}
Note that running your test in the debugger and "watch"ing the variables would have made the problem fairly easy to spot.