I have a task to write down a simple viewer that would show how a .xaml file visually looks like(just like the VS editor, but without editing capabilities). Could you give me any references that would help me?
you can use XamlReader.Load method
If you want only viewer, not a designer you can call XamlReader.Load method, and assign the result to ContentControl.Content
StringReader stringReader = new StringReader(strXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
myContentControl.Content = (Button)XamlReader.Load(xmlReader);
EDIT
This code loads window from xaml and show it
string strXaml = "<Window xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" Title=\"MainWindow\" Height=\"350\" Width=\"525\">" +
"<Grid> <Button Content=\"Button123\" Height=\"23\" HorizontalAlignment=\"Left\" Margin=\"174,41,0,0\" Name=\"button1\" VerticalAlignment=\"Top\" Width=\"75\" />"+
"</Grid></Window>";
StringReader stringReader = new StringReader(strXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Window obj = (Window)XamlReader.Load(xmlReader);
obj.Show();
If you are sure that the root element is allways Window, you can skip it. Something like this works for me
StringReader stringReader = new StringReader(strXaml);
var xDoc = XDocument.Load(stringReader).Document.Descendants().First().DescendantNodes().First();
XmlReader xmlReader = xDoc.CreateReader();
uc.Content = XamlReader.Load(xmlReader);
Would be better to check if Window exists or not before skipping it
You should start by looking at the XamlServices class and its Parse method.
Related
I have to modify a incoming SOAP XML message to add a namespace to one of the elements so that the deserialisation will work. However when I add the xmlns attribute to the correct element, I get an error when I try to load the xml in to an XmlWriter via a stream (which I need to do to in my IClientMessageInspector implementation to replace the Message reply).
The prefix '' cannot be redefined from '' to 'http://www.example.com' within the same start element tag.
I have a work around, which is that after I've modifed the attribute, I reload the entire XML document from it's own OuterXML. This works for some reason, but makes me think there must be a 'correct' way to do this.
Here's a sample test that demonstrates the problem and my current solutions:
[Test]
public void XmlNamespaceTest()
{
var originalXmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><TestElement><Child>thing</Child></TestElement>";
var desiredXmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><TestElement xmlns=\"http://www.example.com\"><Child>thing</Child></TestElement>";
var doc = new XmlDocument();
doc.LoadXml(originalXmlString);
Assert.That(originalXmlString, Is.EqualTo(doc.OuterXml));
// Write this document via an XMLWriter
var ms = new MemoryStream();
var xmlWriter = XmlWriter.Create(ms);
doc.WriteTo(xmlWriter);
xmlWriter.Flush();
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
var originalXmlViaXmlWriter = sr.ReadToEnd();
Assert.That(originalXmlString, Is.EqualTo(originalXmlViaXmlWriter));
// Add the namespace to the element
((XmlElement)doc.GetElementsByTagName("TestElement").Item(0))?.SetAttribute("xmlns", "http://www.example.com");
Assert.That(desiredXmlString, Is.EqualTo(doc.OuterXml));
// Now attempt to write this modified xml via an XMLWriter
ms.SetLength(0);
xmlWriter = XmlWriter.Create(ms);
//Uncomment line below to fix the error.
//doc.LoadXml(doc.OuterXml);
doc.WriteTo(xmlWriter);
xmlWriter.Flush();
ms.Position = 0;
sr = new StreamReader(ms);
var modifedXmlViaXmlWriter = sr.ReadToEnd();
Assert.That(desiredXmlString, Is.EqualTo(modifedXmlViaXmlWriter));
}
According to this you can't change an elements namespace in an XmlDocument. This is also what #LocEngineer found in his comment. The referenced article mentions that the only way to do this is to save and reload the XmlDocument, which is exactly what you are doing.
If you are in a position to use XDoxument instead, it is possible. See this answer for a solution.
When I'm trying to save the XML Document I edited the IOException "file used by another process" occured when I try to save that document.
Any ideas how to solve this?
Note: This method is called everytime a new element in the XmlDocument should be written.
public void saveRectangleAsXMLFragment()
{
XmlDocument doc = new XmlDocument();
doc.Load("test.xml");
XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
String input = generateXMLInput();
xmlDocFrag.InnerXml = input;
XmlElement mapElement = doc.DocumentElement;
mapElement.AppendChild(xmlDocFrag);
input = null;
mapElement = null;
xmlDocFrag = null;
doc.Save("test.xml");
}
Its probably one of your other methods, or other part of the code which opened the file and didnt calose it well. Try to search for this kind of problem.
try this if your's application is only access that .xml file
1. Create a Object globally
object lockData = new object();
2.Use than object to lock statement where you save and load xml
lock(lockData )
{
doc.Load("test.xml");
}
lock(lockData )
{
doc.Save("test.xml");
}
From Jon Skeet's related answer (see https://stackoverflow.com/a/8354736/4151626)
There seems to be a bug in XmlDocument.Save()'s treatment of the file stream, where it becomes pinned and is neither Closed() nor Disposed(). By taking direct control of the creation and disposition of the stream outside of the XmlDocument.Save() I was able to get around this halting error.
//e.g.
XmlWriter xw = new XmlWriter.Create("test.xml");
doc.Save(xw);
xw.Close();
xw.Dispose();
I'm trying to find out why my namespace(xmlns:ren="http://www.example.com/rss2/ext") appears on every custom syndicationItem element (<ren:rssTranslationType typeId="1" xmlns:ren="http://www.example.com/rss2/ext">Original Content</ren:rssTranslationType>) when it's already declared at the top of the file?
Bizarrely this only happens after the .rss file has been read into the syndicationFeed > contents updated > then spat back out. Creating a new rss file works fine (no additional name space usages).
This seemed to cure it:
XmlWriterSettings settings = new XmlWriterSettings{Indent = true, NamespaceHandling = NamespaceHandling.OmitDuplicates};
using (XmlWriter xmlWriter = XmlWriter.Create(sourcePath, settings))
{
rssFeedData.SaveAsRss20(xmlWriter);
}
I am trying to update a canvas from xaml code that i have in a txt file.
What i have done is a save function that saves the canvas that surrounds everything.
Then i am trying to create a load function that opens that txt file and updates the canvas with the data from that file.
But my problem is that it do not update the existing canvas but instedd ad a new one so i have 2.
my question is how do i fix my load function so it do not add a new canvas but only adds the saved canvas children.
Right now my load function locks like this:
if (userClickedOK == true)
{
StreamReader sR = new StreamReader(dlg.FileName);
string text = sR.ReadToEnd();
sR.Close();
StringReader stringReader = new StringReader(text);
XmlReader xmlReader = XmlReader.Create(stringReader);
Canvas canvas1 = (Canvas)System.Windows.Markup.XamlReader.Load(xmlReader);
parentWindow.canvas.Children.Clear(); // clear the existing children
parentWindow.grid.Children.Add(canvas1);
Eddit: new code:
if (userClickedOK == true)
{
StreamReader sR = new StreamReader(dlg.FileName);
string text = sR.ReadToEnd();
sR.Close();
StringReader stringReader = new StringReader(text);
XmlReader xmlReader = XmlReader.Create(stringReader);
parentWindow.canvas = (Canvas)System.Windows.Markup.XamlReader.Load(xmlReader);
parentWindow.grid.Children.Add(parentWindow.canvas);
}
// Nivres
I believe i did solve it.
parentWindow.grid.Children.Remove(parentWindow.canvas);
parentWindow.canvas = (Canvas)System.Windows.Markup.XamlReader.Load(xmlReader);
parentWindow.grid.Children.Add(parentWindow.canvas);
With this i only get one Canvas, but maybe it is the wrong way to go.
I'm trying to create an XML with multiple root elements. I can't change that because that is the way I'm supposed to send the XML to the server. This is the error I get when I try to run the code:
System.InvalidOperationException: This operation would create an incorrectly structured document.
Is there a way to overwrite this error and have it so that it ignores this?
Alright so let me explain this better:
Here is what I have
XmlDocument doc = new XmlDocument();
doc.LoadXml(_application_data);
Now that creates the XML document and I can add a fake root element to it so that it works. However, I need to get rid of that and convert it into a DocumentElement object.
How would I go about doing that?
Specify Fragment when creating XmlWriter as shown here
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.CloseOutput = false;
// Create the XmlWriter object and write some content.
MemoryStream strm = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(strm, settings))
{
writer.WriteElementString("orderID", "1-456-ab");
writer.WriteElementString("orderID", "2-36-00a");
writer.Flush();
}
If it has multiple root elements, it's not XML. If it resembles XML in other ways, you could place everything under a root element, then when you send the string to the server, you just combine the serialized child elements of this root element, or as #Austin points out, use an inner XML method if available.
just create an XML with single root then get it's content as XML text.
you are talking about XML fragment anyways, since good xml has only one root.
this is sample to help you started:
var xml = new XmlDocument();
var root = xml.CreateElement("root");
root.AppendChild(xml.CreateElement("a"));
root.AppendChild(xml.CreateElement("b"));
Console.WriteLine(root.InnerXml); // outputs "<a /><b />"