none
Edit Document Properties with PropertyGrid RRS feed

  • Question

  • I am trying to use a PropertyGrid control to edit and create custom document properties.

    Globals.ThisAddIn.Application.ActiveDocument.BuiltInDocumentProperties returns a dynamic object and I can't work out how to get the PropertyGrid control to bind to this. Has anyone done this before?


    Jacob.

    Tuesday, November 27, 2012 10:59 PM

Answers

  • Hi JBH02,

    Thanks for posting in the MSDN Forum.

    In my opinions, that you need create a new class to warp the Document.BuiltInDocumentProperties due to PropertyGrid need the object have specific attribute for it's work. Following just a sample I will retrieve Subject, Title and Author property and Show them in the PropertyGrid.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;
    using Office = Microsoft.Office.Core;
    using Word = Microsoft.Office.Interop.Word;
    using System.Reflection;
    using System.ComponentModel;
    // TODO:  Follow these steps to enable the Ribbon (XML) item:
    // 1: Copy the following code block into the ThisAddin, ThisWorkbook, or ThisDocument class.
    //  protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
    //  {
    //      return new Ribbon1();
    //  }
    // 2. Create callback methods in the "Ribbon Callbacks" region of this class to handle user
    //    actions, such as clicking a button. Note: if you have exported this Ribbon from the Ribbon designer,
    //    move your code from the event handlers to the callback methods and modify the code to work with the
    //    Ribbon extensibility (RibbonX) programming model.
    // 3. Assign attributes to the control tags in the Ribbon XML file to identify the appropriate callback methods in your code.  
    // For more information, see the Ribbon XML documentation in the Visual Studio Tools for Office Help.
    namespace DocumentProperty
    {
        [ComVisible(true)]
        public class Ribbon1 : Office.IRibbonExtensibility
        {
            private Office.IRibbonUI ribbon;
            private MyDocumentPropertiesWarp _Warp = null;
            public Ribbon1()
            {
            }
            #region IRibbonExtensibility Members
            public string GetCustomUI(string ribbonID)
            {
                return GetResourceText("DocumentProperty.Ribbon1.xml");
            }
            #endregion
            #region Ribbon Callbacks
            //Create callback methods here. For more information about adding callback methods, select the Ribbon XML item in Solution Explorer and then press F1
            public void Ribbon_Load(Office.IRibbonUI ribbonUI)
            {
                this.ribbon = ribbonUI;
            }
            #endregion
            #region Helpers
            private static string GetResourceText(string resourceName)
            {
                Assembly asm = Assembly.GetExecutingAssembly();
                string[] resourceNames = asm.GetManifestResourceNames();
                for (int i = 0; i < resourceNames.Length; ++i)
                {
                    if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
                        {
                            if (resourceReader != null)
                            {
                                return resourceReader.ReadToEnd();
                            }
                        }
                    }
                }
                return null;
            }
            #endregion
            public void ShowProperties(Office.IRibbonControl Control)
            {
                Word.Application wdApp = Globals.ThisAddIn.Application;
                Word.Document wdDoc = wdApp.ActiveDocument;
                _Warp = new MyDocumentPropertiesWarp();
                _Warp.Author = GetWordDocumentPropertyValue(wdDoc,"Author")
                    .ToString();
                _Warp.Subject = GetWordDocumentPropertyValue(wdDoc, "Subject")
                    .ToString();
                _Warp.Title = GetWordDocumentPropertyValue(wdDoc, "Title")
                    .ToString();
                Form1 form = new Form1();
                form.Load += new EventHandler(form_Load);
                form.ShowDialog();
            }
            private object GetWordDocumentPropertyValue(Word.Document document, 
                string propertyName)
            {
                object builtInProperties = document.BuiltInDocumentProperties;
                Type builtInPropertiesType = builtInProperties.GetType();
                object property = builtInPropertiesType.InvokeMember("Item", 
                    BindingFlags.GetProperty, null, builtInProperties, 
                    new object[] { propertyName });
                Type propertyType = property.GetType();
                object propertyValue = propertyType.InvokeMember("Value", 
                    BindingFlags.GetProperty, null, property, new object[] { });
                return propertyValue;
            }
            private void form_Load(object sender, EventArgs e)
            {
                Form1 form = (Form1)sender;
                form.BingProperties(_Warp);
            }
        }
        public class MyDocumentPropertiesWarp
        {
            [CategoryAttribute("Document Properties"), Description("Autor")]
            public string Author { set; get; }
            [CategoryAttribute("Document Properties"), Description("Title")]
            public string Title { set; get; }
            [CategoryAttribute("Document Properties"), Description("Subject")]
            public string Subject { set; get; }
        }
    }

    Form1.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    namespace DocumentProperty
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public void BingProperties(MyDocumentPropertiesWarp Warp)
            {
                propertyGrid1.SelectedObject = Warp;
            }
        }
    }

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, November 29, 2012 2:04 AM
    Moderator

All replies

  • Hi Jacob

    If you mean the Properties window in the Visual Studio IDE then, no, Office Document Properties cannot be displayed or edited in that tool. The Properties in the Visual Studio IDE only link to Visual Studio component properties. Office, even as a VSTO document in the VSTO Designer view, isn't part of the Visual Studio IDE.

    BTW I'm going to move this to the more specific VSTO forum.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, November 28, 2012 7:56 AM
    Moderator
  • So I have an application Add-in that pops up a window that has a propertygrid control on it. Sort of like http://msdn.microsoft.com/en-us/library/aa302326.aspx.

    When I set the PropertyGrid control to use the document properties nothing is displayed.


    Jacob.

    Wednesday, November 28, 2012 8:01 AM
  • you would have to bind to your oown object that implements interface ICustomTypeProvider and return dynamic info based on that object you get from Word API.
    Wednesday, November 28, 2012 8:49 AM
  • So I would need to create my own object that implements ICustomTypeProvider and get the contents of the Globals.ThisAddIn.Application.ActiveDocument.BuiltInDocumentProperties into my custom object collection.

    Is there any way to do this besides enumerating all the document properties and putting them in my customer object collection?


    Jacob.

    Wednesday, November 28, 2012 11:42 PM
  • Hi JBH02,

    Thanks for posting in the MSDN Forum.

    In my opinions, that you need create a new class to warp the Document.BuiltInDocumentProperties due to PropertyGrid need the object have specific attribute for it's work. Following just a sample I will retrieve Subject, Title and Author property and Show them in the PropertyGrid.

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;
    using Office = Microsoft.Office.Core;
    using Word = Microsoft.Office.Interop.Word;
    using System.Reflection;
    using System.ComponentModel;
    // TODO:  Follow these steps to enable the Ribbon (XML) item:
    // 1: Copy the following code block into the ThisAddin, ThisWorkbook, or ThisDocument class.
    //  protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
    //  {
    //      return new Ribbon1();
    //  }
    // 2. Create callback methods in the "Ribbon Callbacks" region of this class to handle user
    //    actions, such as clicking a button. Note: if you have exported this Ribbon from the Ribbon designer,
    //    move your code from the event handlers to the callback methods and modify the code to work with the
    //    Ribbon extensibility (RibbonX) programming model.
    // 3. Assign attributes to the control tags in the Ribbon XML file to identify the appropriate callback methods in your code.  
    // For more information, see the Ribbon XML documentation in the Visual Studio Tools for Office Help.
    namespace DocumentProperty
    {
        [ComVisible(true)]
        public class Ribbon1 : Office.IRibbonExtensibility
        {
            private Office.IRibbonUI ribbon;
            private MyDocumentPropertiesWarp _Warp = null;
            public Ribbon1()
            {
            }
            #region IRibbonExtensibility Members
            public string GetCustomUI(string ribbonID)
            {
                return GetResourceText("DocumentProperty.Ribbon1.xml");
            }
            #endregion
            #region Ribbon Callbacks
            //Create callback methods here. For more information about adding callback methods, select the Ribbon XML item in Solution Explorer and then press F1
            public void Ribbon_Load(Office.IRibbonUI ribbonUI)
            {
                this.ribbon = ribbonUI;
            }
            #endregion
            #region Helpers
            private static string GetResourceText(string resourceName)
            {
                Assembly asm = Assembly.GetExecutingAssembly();
                string[] resourceNames = asm.GetManifestResourceNames();
                for (int i = 0; i < resourceNames.Length; ++i)
                {
                    if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i])))
                        {
                            if (resourceReader != null)
                            {
                                return resourceReader.ReadToEnd();
                            }
                        }
                    }
                }
                return null;
            }
            #endregion
            public void ShowProperties(Office.IRibbonControl Control)
            {
                Word.Application wdApp = Globals.ThisAddIn.Application;
                Word.Document wdDoc = wdApp.ActiveDocument;
                _Warp = new MyDocumentPropertiesWarp();
                _Warp.Author = GetWordDocumentPropertyValue(wdDoc,"Author")
                    .ToString();
                _Warp.Subject = GetWordDocumentPropertyValue(wdDoc, "Subject")
                    .ToString();
                _Warp.Title = GetWordDocumentPropertyValue(wdDoc, "Title")
                    .ToString();
                Form1 form = new Form1();
                form.Load += new EventHandler(form_Load);
                form.ShowDialog();
            }
            private object GetWordDocumentPropertyValue(Word.Document document, 
                string propertyName)
            {
                object builtInProperties = document.BuiltInDocumentProperties;
                Type builtInPropertiesType = builtInProperties.GetType();
                object property = builtInPropertiesType.InvokeMember("Item", 
                    BindingFlags.GetProperty, null, builtInProperties, 
                    new object[] { propertyName });
                Type propertyType = property.GetType();
                object propertyValue = propertyType.InvokeMember("Value", 
                    BindingFlags.GetProperty, null, property, new object[] { });
                return propertyValue;
            }
            private void form_Load(object sender, EventArgs e)
            {
                Form1 form = (Form1)sender;
                form.BingProperties(_Warp);
            }
        }
        public class MyDocumentPropertiesWarp
        {
            [CategoryAttribute("Document Properties"), Description("Autor")]
            public string Author { set; get; }
            [CategoryAttribute("Document Properties"), Description("Title")]
            public string Title { set; get; }
            [CategoryAttribute("Document Properties"), Description("Subject")]
            public string Subject { set; get; }
        }
    }

    Form1.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    namespace DocumentProperty
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            public void BingProperties(MyDocumentPropertiesWarp Warp)
            {
                propertyGrid1.SelectedObject = Warp;
            }
        }
    }

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, November 29, 2012 2:04 AM
    Moderator
  • you can do what Tom suggested, which basically gives you static view of your properties, or yuou can go with ICUstomTypeProvider which is completly dynamic and gives you control about what you want to show, how, etc. based on some runtime condition, not known at compile time (or just writing 100 properties to expose data is too much work )
    Thursday, November 29, 2012 5:53 AM