Can I use DocumentWorksharingEnabled event to add worksets?

Can I use DocumentWorksharingEnabled event to add worksets?

trevor.taylor
Enthusiast Enthusiast
845 Views
2 Replies
Message 1 of 3

Can I use DocumentWorksharingEnabled event to add worksets?

trevor.taylor
Enthusiast
Enthusiast

I would like for additional worksets to be created when a user enables worksets in a project model. DocumentWorksharingEnabled event seems the be the likely candidate for this job. Its documentation states thus:

 

Summary: Subscribe to the DocumentWorksharingEnabled event to be notified when a document has become workshared.

 

Remarks: This event is raised when Revit has just enabled worksharing in the document.

 

Handlers of this event are permitted to make modifications to any document (including the active document), except for documents that are currently in read-only mode.

 

I've written some code (attached) to subscribe to this event and provided an event handler like so:

 

private void CreateSomeWorksetsAtWorksharingStartup(object obj, DocumentWorksharingEnabledEventArgs e)
        {
            Document currentDoc = e.GetDocument();

            if (!currentDoc.IsReadOnly) // Why is the model always read-only?
            {
                CreateSomeWorksets(currentDoc, new string[] { "Workset A", "Workset B", "Workset N" });
            }
        }

The event fires as expected and the handler code executes, but the document is always read-only. I understand from the documentation that the document can only be modified if not in a read-only mode. However, the documentation also seems to indicate that there are times when the current document is editable and can be modified. Is it possible to find the document in a modifiable state when the DocumentWorksharingEnabled event fires in order to create additional worksets?

 

A related question has to do with how I have subscribed to the DocumentWorksharingEnabled event. Why must an Application level event be subscribed to at the Document level? It seems convoluted to use a DocumentOpened or DocumentCreated event to subscribe the DocumentWorksharingEnabled (and then have to set a flag so that I don't re-subscribe each time a new document is opened.) 

 

Thank you in advance for your replies!

 

 

0 Likes
Accepted solutions (1)
846 Views
2 Replies
Replies (2)
Message 2 of 3

Mustafa.Salaheldin
Collaborator
Collaborator
Accepted solution

Please find here the solution

 

 

#region Namespaces

using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.IO;

using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Plumbing;

using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.UI.Events;

//using Autodesk.Revit.Collections;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.Utility;

using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;

#endregion

namespace RevitAddinCS2
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class ExtApp : IExternalApplication
    {
        #region Cached Variables

        public static UIControlledApplication _cachedUiCtrApp;
        private bool m_WorkSharingEnabledEventHasBeenSubscribed = false;
        #endregion

        #region IExternalApplication Members

        public Result OnStartup(UIControlledApplication uiApp)
        {
            _cachedUiCtrApp = uiApp;

            ProductType currentPT = uiApp.ControlledApplication.Product;
            ProductType[] PTsToExclude = new ProductType[] { ProductType.Unknown, ProductType.LT  };
            foreach (ProductType pt in PTsToExclude)
            {
                if (currentPT == pt)
                {
                    return Result.Cancelled;
                }
            }

            try
            {
                RibbonPanel ribbonPanel = CreateRibbonPanel();

                //TODO: add you code below.

                uiApp.Idling += OnIdling;
                return Result.Succeeded;
            }
            catch (Exception ex)
            {
                MessageBox.Show( ex.ToString() );
                return Result.Failed;
            }
        }

        private void OnIdling(object sender, IdlingEventArgs e)
        {
            UIApplication app = sender as UIApplication;
            app.Idling -= OnIdling;
            if (m_WorkSharingEnabledEventHasBeenSubscribed)
            {
                Document currentDoc = app.ActiveUIDocument.Document;

                if (!currentDoc.IsReadOnly) // Why is the model read-only?
                {
                    CreateSomeWorksets(currentDoc, new string[] { "Workset A", "Workset B", "Workset N" });
                }
            }
            else
            {
                app.Application.DocumentWorksharingEnabled += new EventHandler<DocumentWorksharingEnabledEventArgs>(CreateSomeWorksetsAtWorksharingStartup);
            }
            
        }
        private void CreateSomeWorksetsAtWorksharingStartup(object obj, DocumentWorksharingEnabledEventArgs e)
        {
            Document currentDoc = e.GetDocument();
            m_WorkSharingEnabledEventHasBeenSubscribed = true;
            _cachedUiCtrApp.Idling += OnIdling;
        }

        public void CreateSomeWorksets(Document doc, string[] worksetNames)
        {
            using (Transaction tr = new Transaction(doc, "Create new worksets"))
            {
                try
                {
                    tr.Start();
                    WorksetId worksetToActivate = doc.GetWorksetTable().GetActiveWorksetId();
                    WorksetTable wst = doc.GetWorksetTable();

                    foreach (string n in worksetNames)
                    {
                        if (WorksetTable.IsWorksetNameUnique(doc, n))
                        {
                            Workset.Create(doc, n);
                        }
                    }

                    tr.Commit();
                }
                catch (Exception ex) { }
            }
        }

        public Result OnShutdown(UIControlledApplication uiApp)
        {
            try
            {
                //TODO: add you code below.


                return Result.Succeeded;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return Result.Failed;
            }
        }

        #endregion

        #region Local Methods
        
        private RibbonPanel CreateRibbonPanel()
        {
            try{_cachedUiCtrApp.CreateRibbonTab("NSS");}catch{}
            RibbonPanel panel = _cachedUiCtrApp.CreateRibbonPanel("NSS", Guid.NewGuid().ToString());
            
            panel.Name = "NSS_RevitAddinCS2_ExtApp";
            panel.Title = "RevitAddinCS2";

            ////Default button:
            PushButtonData pbDataExtCmd = new PushButtonData("ExtCmd", "ExtCmd", Assembly.GetExecutingAssembly().Location, "RevitAddinCS2.ExtCmd");
            PushButton pbExtCmd = panel.AddItem(pbDataExtCmd) as PushButton;
            pbExtCmd.ToolTip = "ExtCmd";
            pbExtCmd.LargeImage = BmpImageSource("RevitAddinCS2.Resources.ExtCmd32x32.bmp");
            pbExtCmd.Image = BmpImageSource("RevitAddinCS2.Resources.ExtCmd16x16.bmp");

            ////More buttons:


            return panel;
        }

        private System.Windows.Media.ImageSource BmpImageSource(string embeddedPath)
        {
            Stream stream = this.GetType().Assembly.GetManifestResourceStream(embeddedPath);
            var decoder = new System.Windows.Media.Imaging.BmpBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
            
            return decoder.Frames[0];
        }

        #endregion
    }
}

 

Please mark this as a reply if it matches your aim.


¯\_(ツ)_/¯
Let it work like a charm.

Mustafa Salaheldin


EESignature




Digital Integration Manager, DuPod

Facebook | Twitter | LinkedIn

Message 3 of 3

trevor.taylor
Enthusiast
Enthusiast

Thanks Mustafa, your code worked perfectly. I never considered the Idling event. (I'm embarrassed to admit that this is the first time I've used idling!)

0 Likes