Interaction issue between PushButton.Enabled property and IExternalCommandAvailability.IsCommandAvailable callback.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
There is an interaction issue betweenPushButton.Enabled property and IExternalCommandAvailability.IsCommandAvailable check.
IsCommandAvailable method provide control over whether your external command is enabled or disabled and can change PushButton state.
IExternalCommandAvailability.IsCommandAvailable has priority on PushButton.Enabled. So if IsCommandAvailable
return false for the PushButton with Enabled property equals to true the PushButton will be desabled.
IExternalCommandAvailability.IsCommandAvailable callback will be called by Revit's user interface any time there is a contextual change but only for PushButton with Enabled property equals to true.
Change the Enabled property for the PushButton does not invoke IExternalCommandAvailability.IsCommandAvailable callback.
The issue:
In case if PushButton.Enabled property is managed by plugin code and can be changed by http response or as a result of long task execution without interaction with Revit context the PushButton would be stay disabled even when IsCommandAvailable returns true.
Steps to reproduce:
Prerequisites:
- PushButton.Enabled = false;
- Add logic to update PushButton.Enabled property to true without interaction with Revit context.
- Push Button.Availability ClassName set to the class that checks if the document is open.
Steps:
- Open Revit
- Open Document. The PushButton is disabled, so the IsCommandAvailable callback will not be invoked.
- Update PushButton.Enabled property. NOTE: Enabled property change do not invoke IsCommandAvailable callback.
- PushButton is still disabled.
- Click on Ribbon panel. PushButton will be enabled.
Please see code example below for details:
using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Linq;
using System.Reflection;
using System.Windows;
namespace RevitTestPlugin
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class Application : IExternalApplication
{
public Result OnStartup(UIControlledApplication application)
{
var panel = CreateRibbonPanel(application);
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var activeUiDocument = new PushButtonData("ActiveUIDocumentButton", " ActiveUIDocumentButton ", assemblyLocation, "RevitTestPlugin.ActiveUiDocumentExternalCommand");
activeUiDocument.AvailabilityClassName = "RevitTestPlugin.ActiveUiDocumentExternalCommandAvailability";
var button = panel.AddItem(activeUiDocument) as PushButton;
button.Enabled = false;
button.ItemText = "Disabled";
var timer = new System.Timers.Timer(TimeSpan.FromMinutes(5).TotalMilliseconds);
timer.AutoReset = false;
timer.Elapsed += (sender, args) =>
{
button.Enabled = true;
button.ItemText = "Enabled";
};
timer.Start();
return Result.Succeeded;
}
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
private RibbonPanel CreateRibbonPanel(UIControlledApplication application)
{
var tabName = "TestTab";
var panelName = "TestPanel";
application.CreateRibbonTab(tabName);
application.CreateRibbonPanel(tabName, panelName);
var panels = application.GetRibbonPanels(tabName);
return panels.First(p => p.Name == panelName);
}
}
[Transaction(TransactionMode.Manual)]
public class ActiveUiDocumentExternalCommandAvailability : IExternalCommandAvailability
{
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
{
return applicationData.ActiveUIDocument != null; ;
}
}
[Transaction(TransactionMode.Manual)]
public class ActiveUiDocumentExternalCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
MessageBox.Show(nameof(ActiveUiDocumentExternalCommand) + " was clicked");
return Result.Succeeded;
}
}
}
The question is:
- Can I trigger the IExternalCommandAvailability.IsCommandAvailable execution from outside code?
- What is the right way to work with PushButton.Enabled property and IExternalCommandAvailability.IsCommandAvailable callback in such cases?
Thank you for any help.