Buttons Not Being Queried

Discussions related to SoftPro Select user interface development.

Moderator: Phil Barton

Post Reply
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Buttons Not Being Queried

Post by dlerickson »

As an adjunct to this thread (https://devforum.softprocorp.com/viewto ... f=8&t=1384), I've discovered a new problem: buttons that have been registered using the RegisterHandler call, with the proper reference to the handler method, but the query never comes from the runtime.

The specifics of this are: I have four buttons in total, two that are loaded into a custom tab on the top ribbon, and two that are attached to the Order tab (Order tab is referenced in the CTD file as follows:)

Code: Select all

<Guid name="OrderTabCommandSetGuid" value="f436331e-3d02-4b9b-af76-fc878517bcf9">
  <ID name="OrderTab" value="4501" />
</Guid>
Nothing unusual there, and all the buttons in both areas render properly and perform their click-handling functionality as they should. The problem arose when I started to attach a query handler to the buttons, and I noticed that only one of them (which is attached to the Order tab) would ever send queries to the handler method (a common one that I'm using to set permissions on the buttons). No matter what I try (splitting into separate handler methods, thread locking, etc.,) only one button has ever raised a query event.

Do you have any insight as to what might be blocking query events from the other buttons, or if you have seen this behavior in general? It's not a complete show-stopper for me, as I've already put code into the click events to intercept and check permissions before any further processing. It'd be nice to have the button-disabling option pre-click, though.
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Buttons Not Being Queried

Post by BobRichards »

There is only one reason that is happening that I know of.

When you "install" a client package into Select, it is a two step procedure.
  1. Use a Select utility to move some package information to Registry so it can be easily found.
  2. Start Select the with command line option "/setup". This scans all the client packages referenced in registry and creates a list of all UI buttons, windows, and default states that need to be displayed and saves it to a UI file.
We do this to save time startup time since we never have to do this unless a package is added/removed.

When you launch the Select application (without /setup), Select uses this UI file to generate UI components - but it doesn't activate your package. Until the first button is pressed with a handler in your package, the assumption is nothing has changed (it couldn't have - your package is not running).

Look at the client package code below. If you put a breakpoint on the RegisterHandler() line and start Select, you will see that it is not loaded by Select until you push a button that needs to be handled by your specific package. This is a method to speed application startup an prevent loading unnecessary/unused packages. Once your package OnInitialize() is executed (due to a button press), the QueryStatus() method will be called periodically too.

Code: Select all

...
[RegisterPackage("My Company", "My Product", "1.0", "...")]
partial class MyPackage : Package
{
    protected override void OnInitialize()
    {
        //TODO: Provide package initialization logic here.
        this.RegisterHandler(MyPackage.RibbonButton1, RibbonButton1_Invoked, RibbonButton1_QueryStatus);
    }
    
    ...    
If you need the package to be loaded immediately on client startup, the package class must be decorated with a slightly different RegisterPackageAttribute. The optional AutoLoad parameter must be set to True. Now the OnInitialize() method will be called on startup.

Code: Select all

[RegisterPackage("My Company", "My Product", "1.0", "...", true)]
Be aware that in this scenario, some interfaces may not be available yet. If you need to do anything other than set up button handlers, then also subscribe to the IShell.Load event in OnInitialize() and do the remaining work there. IShell.Load is called after all packages have been loaded and the server link is established for the session.
Bob Richards, Senior Software Developer, SoftPro
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Buttons Not Being Queried

Post by dlerickson »

Very helpful stuff, but I of course have additional questions :D

What I'm really trying to do is set button enabled/disable according to some security settings that I'm pulling into the app. Doing this just once on Shell_Load would actually be ideal, as compared to constantly updating with the query status handlers. So, after digging around a bit in the SDK docs, I added some code to the Shell_Load handler which, in turn, calls this method, passing in a list of CommandIDs as params, as follows:

Code: Select all

SetAuthorization(btn_TOB, btn_Inbox_RSS, btn_Inbox_Title, btn_SendToDHIM);
The SetAuthorization method is here:

Code: Select all

private void SetAuthorization(params CommandID[] commandIDs)
{
    if (commandIDs == null || !commandIDs.Any())
        return;

    var commandService = GetService<ICommandCache>();

    if (commandService == null)
        return;

    foreach (var id in commandIDs)
    {
        var resource = AuthorizationProvider.GetResource(this, id);	//AuthorizationProvider is my code to map the CommandID to its permissions

        if (resource == null)
            return;

        var menuCommand = commandService.FindCommand(id);

        if (menuCommand == null)
            continue;

        menuCommand.Enabled = resource.IsAuthorized;
        menuCommand.Reset();
    }
}
The code executes without error, but does not affect the enabled status of the buttons at package startup. I feel like I'm on the right path, but may just need to add/substitute calls to the Shell API to get this to work. What am I doing wrong here, or is this even possible at this stage of package setup?
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Buttons Not Being Queried

Post by BobRichards »

I'm sorry but I just have no idea. I don't go that deep into the button handling startup area.

I am wondering why if a commandID is found, you set a property on it then call Reset() which would restore the object to a predetermined state - not necessarily the one you want. Once again, I did not look into the Select codebase.
Bob Richards, Senior Software Developer, SoftPro
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Buttons Not Being Queried

Post by dlerickson »

Wow, if I've managed to stump you, I'm doing some crazy digging here! :lol:

The call to Reset() was just something I added in to see if it would actually force the button into self-updating after the initial test of this code didn't work. Which also didn't work.

I feel like there's just got to be a way to do this, but figuring out the correct entry point into the API is the trick. I didn't really see anything else in the docs that looked promising, though.
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Buttons Not Being Queried

Post by dlerickson »

Bob, I figured out the problem after doing a search here on "QueryStatus" and finding this: https://devforum.softprocorp.com/viewto ... atus#p1401

As it turns out, on the three buttons that were not firing the QueryStatus events, I had not included "Dynamic" in the style declaration for those buttons in the CTD file, and it had been included on the one button that was working. Once I fixed that, everything started working perfectly. Imagine that!
BobRichards
Posts: 1376
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Buttons Not Being Queried

Post by BobRichards »

Dang! Fantastic. Thanks for sharing. Glad you got it working.
Bob Richards, Senior Software Developer, SoftPro
Post Reply