// XamlHelper.cs
// --------------------------------------------
// 對XAML進行編輯操作的輔助類:
// 對選中的XAML進行操作; 對XAML程式碼進行對齊整理; 對XAML標記進行著色顯示等
// --------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Collections;
using System.Windows;
using System.IO;
using System.Xml;
using System.Windows.Markup;
namespace BrawDraw.Com.Xaml.Utility
{
/// <summary>
/// Provides help functions for processing XAML.
/// </summary>
public class XamlHelper
{
/// <summary>
/// Get XAML from TextRange.Xml property
/// </summary>
/// <param name="range">TextRange</param>
/// <returns>return a string serialized from the TextRange</returns>
public static string GetTextRangeXaml(TextRange range)
{
MemoryStream mstream;
if (range == null)
{
throw new ArgumentNullException("range");
}
mstream = new MemoryStream();
range.Save(mstream, DataFormats.Xaml);
//must move the stream pointer to the beginning since range.save() will move it to the end.
mstream.Seek(0, SeekOrigin.Begin);
//Create a stream reader to read the xaml.
StreamReader stringReader = new StreamReader(mstream);
return stringReader.ReadToEnd();
}
/// <summary>
/// Set XML to TextRange.Xml property.
/// </summary>
/// <param name="range">TextRange</param>
/// <param name="xaml">XAML to be set</param>
public static void SetTextRangeXaml(TextRange range, string xaml)
{
MemoryStream mstream;
if (null == xaml)
{
throw new ArgumentNullException("xaml");
}
if (range == null)
{
throw new ArgumentNullException("range");
}
mstream = new MemoryStream();
StreamWriter sWriter = new StreamWriter(mstream);
mstream.Seek(0, SeekOrigin.Begin); //this line may not be needed.
sWriter.Write(xaml);
sWriter.Flush();
//move the stream pointer to the beginning.
mstream.Seek(0, SeekOrigin.Begin);
range.Load(mstream, DataFormats.Xaml);
}
/// <summary>
/// Parse a string to WPF object.
/// </summary>
/// <param name="str">string to be parsed</param>
/// <returns>return an object</returns>
public static object ParseXaml(string str)
{
MemoryStream ms = new MemoryStream(str.Length);
StreamWriter sw = new StreamWriter(ms);
sw.Write(str);
sw.Flush();
ms.Seek(0, SeekOrigin.Begin);
ParserContext pc = new ParserContext();
pc.BaseUri = new Uri(System.Environment.CurrentDirectory + "/");
return XamlReader.Load(ms, pc);
}
public static string IndentXaml(string xaml)
{
//open the string as an XML node
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xaml);
XmlNodeReader nodeReader = new XmlNodeReader(xmlDoc);
//write it back onto a stringWriter
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
System.Xml.XmlTextWriter xmlWriter = new System.Xml.XmlTextWriter(stringWriter);
xmlWriter.Formatting = System.Xml.Formatting.Indented;
xmlWriter.Indentation = 4;
xmlWriter.IndentChar = ' ';
xmlWriter.WriteNode(nodeReader, false);
string result = stringWriter.ToString();
xmlWriter.Close();
return result;
}
public static string RemoveIndentation(string xaml)
{
if (xaml.Contains("/r/n "))
{
return RemoveIndentation(xaml.Replace("/r/n ", "/r/n"));
}
else
{
return xaml.Replace("/r/n", "");
}
}
public static string ColoringXaml(string xaml)
{
string[] strs;
string value = "";
string s1, s2;
s1 = "<Section xml:space=/"preserve/" xmlns=/"http://schemas.microsoft.com/winfx/2006/xaml/presentation/"><Paragraph>";
s2 = "</Paragraph></Section>";
strs = xaml.Split(new char[] { '<' });
for (int i = 1; i < strs.Length; i++)
{
value += ProcessEachTag(strs[i]);
}
return s1 + value + s2;
}
static string ProcessEachTag(string str)
{
string front = "<Run Foreground=/"Blue/"><</Run>";
string end = "<Run Foreground=/"Blue/">></Run>";
string frontWithSlash = "<Run Foreground=/"Blue/"></</Run>";
string endWithSlash = "<Run Foreground=/"Blue/"> /></Run>";//a space is added.
string tagNameStart = "<Run FontWeight=/"Bold/">";
string propertynameStart = "<Run Foreground=/"Red/">";
string propertyValueStart = "/"<Run Foreground=/"Blue/">";
string endRun = "</Run>";
string returnValue;
string[] strs;
int i = 0;
if (str.StartsWith("/"))
{ //if the tag is an end tag, remove the "/"
returnValue = frontWithSlash;
str = str.Substring(1).TrimStart();
}
else
{
returnValue = front;
}
strs = str.Split(new char[] { '>' });
str = strs[0];
i = (str.EndsWith("/")) ? 1 : 0;
str = str.Substring(0, str.Length - i).Trim();
if (str.Contains("="))//the tag has a property
{
//set tagName
returnValue += tagNameStart + str.Substring(0, str.IndexOf(" ")) + endRun + " ";
str = str.Substring(str.IndexOf(" ")).Trim();
}
else //no property
{
returnValue += tagNameStart + str.Trim() + endRun + " ";
//nothing left to parse
str = "";
}
//Take care of properties:
while (str.Length > 0)
{
returnValue += propertynameStart + str.Substring(0, str.IndexOf("=")) + endRun + "=";
str = str.Substring(str.IndexOf("/"") + 1).Trim();
returnValue += propertyValueStart + str.Substring(0, str.IndexOf("/"")) + endRun + "/" ";
str = str.Substring(str.IndexOf("/"") + 1).Trim();
}
if (returnValue.EndsWith(" "))
{
returnValue = returnValue.Substring(0, returnValue.Length - 1);
}
returnValue += (i == 1) ? endWithSlash : end;
//Add the content after the ">"
returnValue += strs[1];
return returnValue;
}
}
}