Add dynamically created command to dynmically created menu

1145
11
08-18-2010 04:48 AM
CarlosPiccirillo
New Contributor III
Hi everyone,

From an existing custom menu on a custom toolbar called Data, I am trying to create a structure like this and do it all on the fly at run time:

Menu1
    |
    |----Submenu1
    |           |----Command1
    |           |----Command2
    |----Submenu2
    |           |----Command1
    |           |----Command2
    |----Submenu3


Thanks to LOTS of help from the forums, I have been able to create the menus and sub-menus on the fly with no problems but now I am stuct trying to do the same with the commands.

In the example above, if I add an existing ArcMap or custom command previously created to Command1 in Submenu1, the code works fine. If I try to add a new instance of an existing command, the code crashes trying to give it a new UID with an error of, "Value does not fall within the expected range."

        internal static void PopulateDataSubMenu(ICommandBar pMenu, string entitySetName)
        {
            try
            { 
                OleDbConnection dataConnection = new OleDbConnection();
                dataConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
                                                  "Data Source=\\\\ad.sfwmd.gov\\dfsroot\\data\\err_gis\\applications\\dev\\mdb\\rimGISLibDatabase\\mdb\\GISLIBFeaterClassName1.mdb";
                dataConnection.Open();

                OleDbCommand dataCommand = new OleDbCommand();
                dataCommand.Connection = dataConnection;
                dataCommand.CommandText = "SELECT distinct(Order1ClassName) " +
                                          "FROM qryorder1 " +
                                          "WHERE Order1SetName = '" + entitySetName + "'";

                OleDbDataReader dataReader = dataCommand.ExecuteReader();

                object idx = 0;
                int counter = 0;
                while (dataReader.Read())
                {
                    string className = dataReader.GetString(0);
                    idx = counter;
                    CmdTest2 cmdTest3 = new CmdTest2(entitySetName + " - " + className, entitySetName, className);
                    UID uid = new UIDClass();
                    uid.Value = cmdTest3;    <---CRASH HERE       
                    pMenu.Add(uid, ref idx);
                    counter++;
                }

                dataReader.Close();
                dataConnection.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


In the code above, CmdTest2 is a command created using the ESRI BaseCommand template and I am passing it a couple of parameters so that I can use the same command to load different datasets.


Does anyone know how what is going on and how I can fix this?

Thanks,
Carlos
0 Kudos
11 Replies
vincentLahaye
New Contributor II
hi,

you must pass the command name or UID value to UID.value.

example:

uid.Value = "esriEditor.SaveEditsCommand";

or

uid.Value = "{B479F48A-199D-11D1-9646-0000F8037368}";

** you must replace B479F48A-199D-11D1-9646-0000F8037368 by your GUID command value

Vincent
0 Kudos
CarlosPiccirillo
New Contributor III
Vincent,

Thanks for the reply. I've tried both: uid.Value = "RegGSS.cmdTest3"; and
uid.Value = "{adc85ec2-c1c8-48ce-a975-1de2f0b393ff}"; which is the name of the command and the UID of it respectively but I still get the same error.



hi,

you must pass the command name or UID value to UID.value.

example:

uid.Value = "esriEditor.SaveEditsCommand";

or

uid.Value = "{B479F48A-199D-11D1-9646-0000F8037368}";

** you must replace B479F48A-199D-11D1-9646-0000F8037368 by your GUID command value

Vincent
0 Kudos
vincentLahaye
New Contributor II
Hi,

replace : UID uid = new UIDClass();

by

UID uid = new UID();
0 Kudos
CarlosPiccirillo
New Contributor III
This produces the same error as before, "Value does not fall within the expected range."

                    string className = dataReader.GetString(0);
                    idx = counter;
                    CmdTest2 cmdTest3 = new CmdTest2(entitySetName + " - " + className, entitySetName, className);
                    UID uid = new UID();
                    uid.Value = "RegGSS.cmdTest3";
                    pMenu.Add(uid, ref idx);
                    counter++;


This produces a new error, "command not available."

                    string className = dataReader.GetString(0);
                    idx = counter;
                    CmdTest2 cmdTest3 = new CmdTest2(entitySetName + " - " + className, entitySetName, className);
                    UID uid = new UID();
                    uid.Value = "{adc85ec2-c1c8-48ce-a975-1de2f0b393ff}";
                    pMenu.Add(uid, ref idx);
                    counter++;


I don't think my second attempt is correct at all because the uid number is for the original command, CmdTest2, not the new instance, cmdTest3.

Since adding an existing ArcGIS command and prexisting user created command (CmdTest2) works, it is starting to sound to me like you cannot create a new instance of a command and immediately add it to a menu but that too doesn't sound right. I messed with IMultiItem a bit too but could not get it working for my needs.

Thanks again for your time and effort!
0 Kudos
vincentLahaye
New Contributor II
You're right,

your command must be register before you can use it.  Maybe you can try to register your new command with a new guid. After this, try to add it in the menu.  I don't know if you can get a random GUID from a tool available with arcobject. I think, if it's possible, you can generate your command dynamically.
0 Kudos
CarlosPiccirillo
New Contributor III
I have been able to create menu items dynamically using ICommandItem and assigning them previously created custom commands with the code below but this approach does not seem to apply to a new instance of an existing command and I have no clue how to register the new instance.

          
         ICommandBar pSetEditMenu = pDataEditorMenu.CreateMenu("SetEditLayer", ref idx);
                    ICommandItem pSetEditItem = pSetEditMenu as ICommandItem;
                    pSetEditItem.Caption = "Set Edit Layer";

                    idx = 0;
                    pSetEditMenu.Add(MakeUID("RegGSS.Commands.CmdSetEditLayerScratchLine"), ref idx);
                    idx = 1;
                    pSetEditMenu.Add(MakeUID("RegGSS.Commands.CmdSetEditLayerScratchPoly"), ref idx);

        internal static UID MakeUID(string id)
        {
            try
            {
                UID uid = new UIDClass();
                uid.Value = id;
                return uid;
            }
            catch (Exception ex)
            {
                ClsLogErrors.LogError(ex.StackTrace, ex.Message, "MakeUID", null);
                MessageBox.Show("An error has occured." + "\r\n" + "The GIS group has been notified of this problem.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return null;
            }
0 Kudos
vincentLahaye
New Contributor II
Question for you:

Do you really need to create a new instance of your command?  Why just not pass same UID?  It will be 2 input in menu bar, but it will call the same command. 

If your command do 2 differents operation, it's better to split this command in 2 distinct command.  Else, juste add same UID in your commandItem.

Vincent
0 Kudos
AndrewMay
New Contributor
I think Neil is correct (see http://forums.arcgis.com/threads/11252-Creating-a-command-dynamially-at-run-time), you can't create commands dynamically at runtime.  You can add them at runtime but I think you still need to have created them before.

Why do you need to have your commands on a toolbar?  Could you instead create a window and dynamically create menus and tools on there for the user?  This should be a lot simpler (i.e. you avoid all the difficulties you're having with command/toolbars/menus/etc) and still give your users a dynamically created list of commands.
Hope this helps.
0 Kudos
CarlosPiccirillo
New Contributor III
Dr. May,

Thanks for the reply. We have our custom commands on a toolbar because the toolbar has a lot more things on it than just the Data menu/submenus/commands that I am trying to create dynamically. PLus, my boss wants everything on a toolbar so that users can just turn it on whenever they need to use the functionality we provide for them just like an ESRI or third-party toolbar. Also, the toolbar has over 20 customs tools as well and as far I know, tools must reside on a toolbar. Please correct me if I am wrong however.

I am intrigued by your suggestion however, what do you mean by "create a window?"
0 Kudos