I have been stuck on this problem for the last 2 days and still haven't made it work and I am looking for some help.
My Listbox gets generated items added to it depending on the item selected in the Combobox. When I click the button Create a new Window appears with a WebBrowser object inside of it.
(Wasnt allowed to upload image so it is contained in the link)
This is the screen with the list box with the items generated and also the button that is clicked.
http://imgur.com/6B8GO1m
Button Click Event
This gets the item selected in the Combobox. Then it creates a new instance of the Alrighty Class with the property called Standards with the List of items (The items from the Listbox). The property gets populated with the third line and then I have another class named SaveXML (See Below) and this saves in XML. Then will open the browser.
string selectedStandard = (string)cmbStandard.SelectedItem;
Alrighty info = new Alrighty();
info.Standards = _standardDefinitions;
SaveXML.SaveData(info, string.Format("{0}.xml", selectedStandard));
HTMLBrowser boss = new HTMLBrowser(selectedStandard);
boss.Show();
SaveXML Class
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();
}
The Problem
When I click the button and get onto the Window with the Web Browser on this code appears:
http://imgur.com/zF465n5
As you can see from the blue box, When I delete this code and add the code in for my Stylesheet everything works fine, but the problem is the code in the blue box keeps getting generated, is there a way to not get this code in the XML file that is created.
Extra
How can I get this string to appear instead of the generated code in the blue box:
<?xml-stylesheet type="text/xsl" href="StandardXS.xsl"?>
EDIT:
public class SaveXML
{
public static void SaveData(object obj, string filename)
{
//empty namespace and empty value
XmlSerializerNamespaces alright = new XmlSerializerNamespaces();
alright.Add("", "");
XmlSerializer sr = new XmlSerializer(obj.GetType());
TextWriter writer = new StreamWriter(filename);
sr.Serialize(writer, obj, alright);
writer.Close();
}
public void WriteXml(XmlWriter writer) { writer.WriteAttributeString(#"<?xml-stylesheet type=text/xsl href=StandardXS.xsl?>", string.Empty); }
}
You can do it like this:
XmlSerializerNamespaces namespace = new XmlSerializerNamespaces();
//empty namespace and empty value
namespace.Add("", "");
XmlSerializer serializer = new XmlSerializer(someType);
//Serialize the object with custom namespace
serializer.Serialize(xmlTextWriter, myObj, namespace);
For adding a custom attribute, as I said in the comments, implement IXmlSerializable and implement WriteXml and add your custom attribute.
Related
TLDR; Please either confirm that the 2nd code snippit is the accepted method for creating a CustomXmlPart or show me another less tedious method.
So I'm trying to embed some application data in some of the elements in a .pptx that I'm modifying using the OpenXmlSDK.
To explain briefly, I need to embed an chart code into each image that is loaded into the presentation. It's so that the presentation can be re-uploaded and the charts can be generated again then replaced using the newest data.
Initially I was using Extended Attributes on the OpenXmlElement itself:
//OpenXmlDrawing = DocumentFormat.OpenXml.Drawing
// there's only one image per slide for now, so I just grab the blip which contains the image
OpenXmlDrawing.Blip blip = slidePart.Slide.Descendants<OpenXmlDrawing.Blip>().FirstOrDefault();
//then apply the attribute
blip.SetAttribute(new OpenXmlAttribute("customAttribute", null, customAttributeValue));
The issue with that being, when the .pptx is edited in PowerPoint 2013, it strips out all the Extended Attributes.
SO.
I've read in multiple places now that the solution is to use a CustomXmlPart.
So I was trying to find how to do it.. and it was looking like it would require me to have a separate file for each CustomXmlPart to feed into the part. Ex/
var customXmlPart = slidePart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
customXmlPart.FeedData(stream);
}
^ and that would need to be repeated with a different file for each CustomXmlPart. Which then means I'd likely just have to have a template file containing a skeleton custom XML part, and then dynamically fill in its contents for each individual slide before feeding it into the custom xml part.
It seems like a heck of a lot of work just to put in a little custom attribute. But I haven't been able to find any alternative methods.
Can anyone please either confirm that this is indeed the way I should do it, or point me in another direction? Greatly appreciated.
The answer is yes! :)
public class CustomXMLPropertyClass
{
public string PropertyName { get; set; }
public string PropertyValue { get; set; }
}
private static void AddCustomXmlPartCustomPropertyToSlidePart(string propertyName, string propertyValue, SlidePart part)
{
var customXmlPart = part.AddCustomXmlPart(CustomXmlPartType.CustomXml);
var customProperty = new CustomXMLPropertyClass{ PropertyName = propertyName, PropertyValue = propertyValue };
var serializer = new System.Xml.Serialization.XmlSerializer(customProperty.GetType());
var stream = new MemoryStream();
serializer.Serialize(stream, customProperty);
var customXml = System.Text.Encoding.UTF8.GetString(stream.ToArray());
using ( var streamWriter = new StreamWriter(customXmlPart.GetStream()))
{
streamWriter.Write(customXml);
streamWriter.Flush();
}
}
and then to get it back out:
private static string GetCustomXmlPropertyFromCustomXmlPart(CustomXmlPart customXmlPart)
{
var customXmlProperty = new CustomXMLPropertyClass();
string xml = "";
using (var stream = customXmlPart.GetStream())
{
var streamReader = new StreamReader(stream);
xml = streamReader.ReadToEnd();
}
using (TextReader reader = new StringReader(xml))
{
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(customXmlProperty));
customXmlProperty = (CustomXMLPropertyClass)serializer.Deserialize(reader);
}
var customPropertyValue = customXmlProperty.PropertyValue;
return customPropertyValue;
}
You could also try custom properties. Custom XML files are meant for complex objects, and it sounds like you only need to store simple information.
I have work with a MainWindow.xaml class and I want to save some values of my class in my case: private static int bestrecord = 0;
How can I save this value and restore it without a created class just for it?
Because with Serialization you can save only an object and I just want to save this variable.
Thank you.
You can use Application Settings functionality, which is pretty much designed for saving simple variables which are part of the application state, and need to be restored in future sessions.
The documentation is here.
Once you've creating a setting using the designer in the IDE, you can load settings like this:
var mySetting = Properties.Settings.Default.MySettingName;
You can edit your variable normally and save it like this
Properties.Settings.Default.MySettingName = mySetting ;
Properties.Settings.Default.Save();
I have found a very good way for save my score in xml file.
I'm based on Examples of XML Serialization.
For do that i have create 2 function:
private void SerializeElement()
{
XmlSerializer ser = new XmlSerializer(typeof(XmlElement));
XmlElement myElement = new XmlDocument().CreateElement("bestRecord");
myElement.InnerText = bestRecord.ToString();
TextWriter writer = new StreamWriter("text.xml");
ser.Serialize(writer, myElement);
writer.Close();
}
and
private static int deserialize()
{
XmlSerializer ser = new XmlSerializer(typeof(XmlElement));
StreamReader lecteur = new StreamReader("text.xml");
XmlDocument myElement = new XmlDocument();
XmlElement p = (XmlElement) ser.Deserialize(lecteur);
lecteur.Close();
return int.Parse(p.InnerText);
}
the xml file look like:
<?xml version="1.0" encoding="utf-8"?>
<bestRecord>8</bestRecord>
I use the below line of code in my program. I get the value through textBox3.Text and then append it to the comboBox that already has two values.
comboBox2.Items.Add(textBox3.Text);
It is adding the value to the application at run-time. But, once I close the application and run the application again, the newly added value is not featuring in the drop down menu.
How to save the value to the comboBox2 collections. All the manuals/posts, are pointing to only Add method to add values to the items. Am I missing something....
When you close the app, you can save your ComboBox items via serialization:
First, go ahead and create any class and decorate it with the Serializable attribute. Next, add a field of type List<string> and a blank constructor to it like this:
[Serializable]
public class UserData //You can name this anything you like.
{
public List<string> Data = new List<string>();
public UserData() { }
}
Next, when you close the app, or maybe during some other action like clicking a save button use this code:
UserData uData = new UserData();
foreach (object i in comboBox1.Items) // Change name of ComboBox if necessary.
{
uData.Data.Add(i.ToString());
}
XmlSerializer xs = new XmlSerializer(typeof(UserData));
using (FileStream fs = new FileStream("userData.xml", FileMode.OpenOrCreate)) // Change path accordingly.
{
xs.Serialize(fs, uData);
}
To read the data during app startup use this code:
XmlSerializer xs = new XmlSerializer(typeof(UserData));
UserData deserializedData; // This is the retrieved data. Use this after the following Using Block
using (FileStream fs = new FileStream("userData.xml", FileMode.OpenOrCreate)) //Again, change the path accordingly
{
deserializedData = (UserData)xs.Deserialize(fs);
}
//Now deserializedData contains the read data.
comboBox1.Items.Clear(); // Delete all items...
comboBox1.Items.AddRange(deserializedData.Data.ToArray<Object>()); //...and add the retrieved items
I have a server control that has a PlaceHolder that is an InnerProperty. In the class when rendering I need to get the text / HTML content that is supposed to be in the PlaceHolder. Here is a sample of what the front end code looks like:
<tagPrefix:TagName runat="server">
<PlaceHolderName>
Here is some sample text!
</PlaceHolderName>
</tagPrefix:TagName>
This all works fine except I do not know how to retrieve the content. I do not see any render methods exposed by the PlaceHolder class. Here is the code for the server control.
public class TagName : CompositeControl
{
[TemplateContainer(typeof(PlaceHolder))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public PlaceHolder PlaceHolderName { get; set; }
protected override void RenderContents(HtmlTextWriter writer)
{
// i want to retrieve the contents of the place holder here to
// send the output of the custom control.
}
}
Any ideas? Thanks in advance.
I just found the solution. I did not see the render methods because of the context of how I was using the PlaceHolder object. Eg I was trying to use it as a value and assign it to a string like so:
string s = this.PlaceHolderName...
Because it was on the right hand side of the equals Intellisense did not show me the render methods. Here is how you render out a PlaceHolder using and HtmlTextWriter:
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
this.PlaceHolderName.RenderControl(htw);
string s = sw.ToString();
Posting this as a second answer so I can use code formatting. Here is an updated method that uses Generics and also uses the 'using' feature to automatically dispose the text / html writers.
private static string RenderControl<T>(T c) where T : Control, new()
{
// get the text for the control
using (StringWriter sw = new StringWriter())
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
c.RenderControl(htw);
return sw.ToString();
}
}
This is killing me. I've read these:
http://msdn.microsoft.com/en-us/library/athddy89(v=VS.80).aspx
http://msdn.microsoft.com/en-us/library/2baksw0z(v=VS.80).aspx
But I don't see how to apply them to what I'm trying to do. I want to customize the way the following list serializes...
[Serializable]
public class FinalConcentrations : List<string> { }
so that when I pass it as the "objectToSerialze" to this...
public void serializeObject(object objectToSerialize, Stream outputStream)
{
// removes the default added namespaces
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serial = new XmlSerializer(objectToSerialize.GetType());
MemoryStream ms = new MemoryStream();
serial.Serialize(ms, objectToSerialize, ns);
StreamReader reader = new StreamReader(ms);
ms.Position = 0;
ms.WriteTo(outputStream);
}
...it writes this to the output stream:
<FinalConcentrations>
<FinalConcentration>string value 1</FinalConcentration>
<FinalConcentration>string value 2</FinalConcentration>
<FinalConcentration>string value 3</FinalConcentration>
</FinalConcentration>
...instead of this
<FinalConcentrations>
<string>string value 1</string>
<string>string value 2</string>
<string>string value 3</string>
</FinalConcentration>
My serializeObject method is used to serialize a wide variety of objects, so I'm looking for a way to do this in my FinalConcentrations definition rather than within that method.
Please, help.
The easiest way to fix that is to pass in a wrapper object instead of the list itself, i.e.
public class FinalConcentrations {
private readonly List<string> items = new List<string>();
[XmlElement("FinalConcentration")]
public List<string> Items {get {return items;}}
}
that do?
Well, when I ran your example I actually got
<?xml version="1.0"?>
<ArrayOfString>
<string>Red</string>
<string>Green</string>
<string>Blue</string>
</ArrayOfString>
but by changing
[Serializable, XmlRoot( ElementName= "FinalConcentrations")]
public class FinalConcentrations : List<string> { }
I got
<?xml version="1.0"?>
<FinalConcentrations>
<string>Red</string>
<string>Green</string>
<string>Blue</string>
</FinalConcentrations>
QED?
There are a whole bunch of XML decorator attributes that can change the serialisation, eg. XmlElement. Worth having a look at.
Best of luck.