Access UIDocument, Document from anywhere???

Access UIDocument, Document from anywhere???

aclarke
Advocate Advocate
5,039 Views
8 Replies
Message 1 of 9

Access UIDocument, Document from anywhere???

aclarke
Advocate
Advocate

I struggle with this so much, I just don't understand how it works, I wish to know how to pass & access the UIDocument, Document from ANYWHERE.

 

My code below, "MySelectedElement(uidoc, doc)" has red squiggles how do I access uidoc, and doc from anywhere?

or create an object at will so I can access it.

 

Thanks

 

MySelectedElement(uidoc, doc); //<--- Method Call

 

namespace PreFab_AssemblyNumber
{
    [TransactionAttribute(TransactionMode.Manual)]
    public partial class RibbonTab_ModifyActive : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            #region !--> Load Document and UIDocument <--!

            UIApplication app = commandData.Application;
            UIDocument uidoc = app.ActiveUIDocument;
            Document doc = app.ActiveUIDocument.Document;

            #endregion Load Document and UIDocument

            #region t.start
            Transaction t = new Transaction(doc, "PreFab Number");
            t.Start();
            #endregion t.start

            //-----------------------------------------------------------------------------------------
            // **** CODE *******************************************************************************
            //-----------------------------------------------------------------------------------------

            FireEvent.PreFabEvent(uidoc, doc);

            //-------------------------------------------------------------------------------------
            // **** CODE ***************************************************************************
            //-------------------------------------------------------------------------------------

            #region t.commit
            t.Commit();
            #endregion t.commit

            return Result.Succeeded;

        }

        // ----------------------------------------------------------------------------------------
        // ****************************************************************************************
        // ----------------------------------------------------------------------------------------

        public static TaskDialogResult TD(string str)
        {
            return TaskDialog.Show("showTask", str);
        }

        public static TaskDialogResult TD(object obj)
        {
            return TaskDialog.Show("showTask", $"{obj}");
        }

        // ----------------------------------------------------------------------------------------

        public class FireEvent
        {

            public static void PreFabEvent(UIDocument uidoc, Document doc)
            {
                // RibbonControl is the main Ribbon entry point, this is the Ribbon
                Autodesk.Windows.RibbonControl ribbon = Autodesk.Windows.ComponentManager.Ribbon;

                foreach (Autodesk.Windows.RibbonTab tab in ribbon.Tabs)
                {
                    if (tab.Title == "Modify")
                    {
                        tab.PropertyChanged += EventMethods.PanelEvent;
                        break;
                    }
                }
            }

        // ----------------------------------------------------------------------------------------

            public class EventMethods
            {
                public static void PanelEvent(object sender, System.ComponentModel.PropertyChangedEventArgs e)
                {
                    // List of Modify Tabs to trigger Event
                    List<string> listOfModifyTabs = new List<string>
                    {
                        "Modify | Generic Models",
                        "Modify | Lighting Fixtures",
                        "Modify | Fire Alarm Devices",
                        "Modify | Electrical Fixtures"
                    };

                    Autodesk.Windows.RibbonControl ribbon = Autodesk.Windows.ComponentManager.Ribbon;

                    if (sender is Autodesk.Windows.RibbonTab)
                    {
                        if (e.PropertyName == "Title")
                        {
                            foreach (Autodesk.Windows.RibbonTab t in ribbon.Tabs)
                            {
                                foreach (string s in listOfModifyTabs)
                                {
                                    if (t.Title == s)
                                    {
                                        MySelectedElement(uidoc, doc); //<--- Method Call
                                    }
                                }
                            }
                        }
                    }
                }

            }

        // ----------------------------------------------------------------------------------------

            private static void MySelectedElement(UIDocument uidoc, Document doc)
            {
                Guid guid = new Guid("343cc1fc-0a53-48e3-bce9-c5adcc118b0e"); //<-- Build function to return GUID from Shared Param file

                if (uidoc.Selection.GetElementIds().Count() == 1)
                {
                    Element e = doc.GetElement(uidoc.Selection.GetElementIds().ToList()[0]);
                    foreach (Parameter p in e.Parameters)
                    {
                        if (p.IsShared && p.GUID.Equals(guid))
                        {
                            TD(p.Definition.Name);
                        }
                    }
                }
            }
        }
    }
}

 

0 Likes
Accepted solutions (1)
5,040 Views
8 Replies
Replies (8)
Message 2 of 9

aclarke
Advocate
Advocate

I believe it was as simple as:

UIDocument uidoc = null;

Document doc = null;

 

 

 

0 Likes
Message 3 of 9

aclarke
Advocate
Advocate

Nope, not so simple, all I created is a 'null'....  booo ;(

0 Likes
Message 4 of 9

RPTHOMAS108
Mentor
Mentor

Perhaps describe in words what you are trying to do?

 

It seems you are using unofficial approaches to achieve something. Perhaps by changing your aspirations in terms of the exact user interaction required you could do it the official way. UIDocument and Document are null because you likely exit the context before you use them i.e.

 

IExternalCommand executes, halfway through a non API event handler is added for a ribbon item, IExternalCommand ends, execution returns to Revit, Revit raises events for ribbon item, handler uses variable GC'ed already perhaps?

0 Likes
Message 5 of 9

eason.kangEDLV4
Autodesk Support
Autodesk Support
Accepted solution

Not sure why you want to use so many static functions... here is the shortcut: Store them as the static variables of the RibbonTab_ModifyActive, but this is not a good practice in C#.

 

public partial class RibbonTab_ModifyActive : IExternalCommand
{	
	public static UIApplication UIApp { get; private set; }

	public static UIDocument UIDoc
	{ 
		get
		{
			return UIApp.ActiveUIDocument;
		}
	}

	public static Document Doc
	{ 
		get
		{
			return UIDoc.Document;
		}
	}

    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        #region !--> Load Document and UIDocument <--!

        RibbonTab_ModifyActive.UIApp = new UIApplication(commandData.Application.Application);

        //
     }
 }


// function call
MySelectedElement(RibbonTab_ModifyActive.UIDoc, RibbonTab_ModifyActive.Doc);

 

 

Therefore, I would advise you to move your static functions into RibbonTab_ModifyActive as non-static member functions. Or, create non-static classes, then pass UIDocument & Document into their constructor/member functions.

 

Cheers,

 

 


Eason Kang
Developer Advocate
Developer Advocacy & Support Service
Autodesk Platform Service (formerly Forge)

Message 6 of 9

aclarke
Advocate
Advocate

Thank you,

Exactly what I was looking for.

 

What do you mean this is not good practice in C#. 

If I take your there for advice, would this change it to 'good practice' ?

 

Thank you for the advice, I plan to refactor all my statics, I am only testing thoughts, and I am still very new to OOP and C#.

 

Thanks

0 Likes
Message 7 of 9

longt61
Advocate
Advocate

I would really appreciate if you could explain further what you mean by "this is not good practice in C#".

As of my experience, I would put the application inside a Revit IExternalApplication, where it stay there for good. from Revit start up until Revit shut down. The application are meant to be used in the whole session, then it should belong to something that lasts the whole session.

Message 8 of 9

eason.kangEDLV4
Autodesk Support
Autodesk Support

Hi,

 

It's just a common scene while writing codes. You may google it on the internet. There are lots of references, and here are some links I found with the keyword "c# static member variable best practices":

 

 

From Revit API respective, those API objects you used (e.g., ExternalCommandData, DB Document, etc.) will change when the user clicks on your Add-In or changes the active Revit document. However, these static member variables are still here and occupying the computer memory unless you manually set them to null before IExternalCommand#Execute returns a Result object.

 

As a good programmer, we should always take care of how the computer memory we used in our Add-In to prevent running out of the memory, and then your users must close Revit to release them. About garbage collecting on static members, check here: https://stackoverflow.com/questions/6600093/do-static-members-ever-get-garbage-collected

 

Hope it's enough for you.

 

Cheers,


Eason Kang
Developer Advocate
Developer Advocacy & Support Service
Autodesk Platform Service (formerly Forge)

Message 9 of 9

aclarke
Advocate
Advocate

Thank you for coming back and explaining.  This does make sense to me from your explanation.

Common sense is only common when one has experience, thank you for sharing yours...  🙂

 

Thank you lingt61 for re-asking this question and much more politer than myself.

0 Likes