public void AddCustomProperty(CustomProperty cp)
{
// If this document does not contain a customFilePropertyPart create one.
if (!package.PartExists(new Uri("/docProps/custom.xml", UriKind.Relative)))
HelperFunctions.CreateCustomPropertiesPart(this);
XDocument customPropDoc;
PackagePart customPropPart = package.GetPart(new Uri("/docProps/custom.xml", UriKind.Relative));
using (TextReader tr = new StreamReader(customPropPart.GetStream(FileMode.Open, FileAccess.Read)))
customPropDoc = XDocument.Load(tr, LoadOptions.PreserveWhitespace);
// Each custom property has a PID, get the highest PID in this document.
IEnumerable<int> pids =
(
from d in customPropDoc.Descendants()
where d.Name.LocalName == "property"
select int.Parse(d.Attribute(XName.Get("pid")).Value)
);
int pid = 1;
if (pids.Count() > 0)
pid = pids.Max();
// Check if a custom property already exists with this name
// 2013-05-25: IgnoreCase while searching for custom property as it would produce a currupted docx.
var customProperty =
(
from d in customPropDoc.Descendants()
where (d.Name.LocalName == "property") && (d.Attribute(XName.Get("name")).Value.Equals(cp.Name, StringComparison.InvariantCultureIgnoreCase))
select d
).SingleOrDefault();
// If a custom property with this name already exists remove it.
if (customProperty != null)
customProperty.Remove();
XElement propertiesElement = customPropDoc.Element(XName.Get("Properties", customPropertiesSchema.NamespaceName));
propertiesElement.Add
(
new XElement
(
XName.Get("property", customPropertiesSchema.NamespaceName),
new XAttribute("fmtid", "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"),
new XAttribute("pid", pid + 1),
new XAttribute("name", cp.Name),
new XElement(customVTypesSchema + cp.Type, cp.Value ?? "")
)
);
// Save the custom properties
using (TextWriter tw = new StreamWriter(new PackagePartStream(customPropPart.GetStream(FileMode.Create, FileAccess.Write))))
customPropDoc.Save(tw, SaveOptions.None);
// Refresh all fields in this document which display this custom property.
UpdateCustomPropertyValue(this, cp.Name, (cp.Value ?? "").ToString());
}