Openxml - 锁定所有内容控件

时间:2012-09-17 03:10:15

标签: c# .net openxml

我想以编程方式锁定所有内容控件,以便用户无法删除它们。

我使用的是以下代码,但我的问题是,在少数情况下,我在调用null时收到elem.SdtProperties.ChildElements.First<WP.Lock>()

有人可以帮我完成下面提到的代码吗?

static void MakeContentControlsNonDeletable()
        {
            using (P.WordprocessingDocument wordDoc =
              P.WordprocessingDocument.Open(@"c:\XYZ.docx", true))
            {
                IEnumerable<WP.SdtElement> elements =
                  wordDoc.MainDocumentPart.Document.Descendants<WP.SdtElement>();

                foreach (WP.SdtElement elem in elements)
                {
                    if (elem.SdtProperties != null)
                    {
                        WP.Lock l = elem.SdtProperties.ChildElements.First<WP.Lock>();

                        if (l == null)
                        {
                            //Please help here
                            //Please help here
                            //Please help here
                            //Please help here
                        }

                        if (l.Val != WP.LockingValues.SdtContentLocked && l.Val != WP.LockingValues.SdtLocked)
                        {
                            Console.WriteLine("Unlock content element...");
                            l.Val = WP.LockingValues.SdtLocked;
                        }
                    }
                }
            }

1 个答案:

答案 0 :(得分:1)

看来你的代码很好。我之前在另一个有某个对象并且返回null的场景中遇到了同样的问题。我不知道openxml sdk在那时有什么问题,但我可以告诉你我是如何解决的。

问题基本上是在结构深处的某些点你知道有一个元素应该被解释为一个Lock对象,但是sdk只能看到它作为OpenXmlElement(不是它的子类Lock对象),所以这就是为什么当你做First<WP.Lock>()你期望一个Lock对象,你知道它在那里,但你只是得到null。我所做的就是将所有内容视为OpenXmlElement而忘记强类型。

static void MakeContentControlsNonDeletable()
    {
        using (P.WordprocessingDocument wordDoc =
          P.WordprocessingDocument.Open(@"c:\XYZ.docx", true))
        {
            IEnumerable<OpenXmlElement> elements =
              wordDoc.MainDocumentPart.Document.Descendants<>(child => child.LocalName == "sdt");

            foreach (OpenXmlElement elem in elements)
            {
                if (elem.ChildElements.Any(child => child.LocalName == "sdtPr"))
                {
                    OpenXmlElement sdtPr = elem.ChildElements.FirstOrDefault(child => child.LocalName == "sdtPr");
                    OpenXmlElement l = sdtPr.ChildElements.FirstOrDefault(child => child.LocalName == "lock");

                    if (l == null) //At this point if you have your lock object this isn't null
                    {
                        //Please help here
                        //Please help here
                        //Please help here
                    }

                    OpenXmlAttribute valAttribute = l.GetAttribute("val", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
                    if (valAttribute != null) {
                         valAttribute = new OpenXmlAttribute();
                    }

                    if (valAttribute.Value != "sdtContentLocked" && valAttribute.Value != "sdtLocked")
                    {
                        Console.WriteLine("Unlock content element...");
                        valAttribute.Value = "sdtLocked";
                    }
                }
            }
        } 

我知道这不是它应该的方式,我知道所有对象都应该强烈地输入到各自的openxml sdk类中,但是这种情况发生了很多,这就是我这样做的原因。

希望有所帮助