主题:演示如何使用 PostCommand() 推动用户工作流程

摘要:使用 PostCommand() 作为自定义工作流程的一部分。当文档没有添加新的修订版本时,在保存之前提示添加一个。

项目文件:

·Application.cs - 实现 Revit 插件接口 IExternalApplication

·PostCommandRevisionMonitorCommand.cs - 设置修订监视器并执行与之相关的任务的外部命令。

·PostCommandRevisionMonitor.cs - 此类具有在文档保存时提示用户

描述:

此示例演示了如何使用 PostCommand() 方法和各种事件来推动用户工作流程。在此示例中,需要的行为是在保存文档之前让用户创建一个新的修订版本。如果没有添加新的修订版本,则会阻止保存,并自动将用户输入到“工作表/修订版编辑”命令中。完成添加修订之后,外部事件会再次发布保存命令。

事件和活动的工作流如下:

·用户尝试保存

·调用 BeforeSaving 事件

·提示用户缺少新的修订版本的消息

·设置 TaskDialogShowing 事件

·设置 ExternalEvent

·取消 BeforeSaving

·调用 TaskDialogShowing 事件

·关闭有关文档未保存的 TaskDialog

·发布问题工作表/修订版(PostCommand()

·在此命令的 BeforeExecuting 事件中,引发 ExternalEvent(在命令结束后立即回调)

·用户添加新的修订版本并关闭对话框

·调用 IExternalEventHandler

·删除不需要的事件发布保存命令(PostCommand())。

·保存结束

说明:

打开 Revit 和任何可编辑项目。

1.点击“添加-ins->UI->设置修订版本监视器”按钮。

2.对项目进行任何编辑(除了添加新的修订版本)

3.点击保存命令。

4.注意有关需要新修订版本的任务对话框弹出。

5.选择添加修订版本

6.注意发布的问题工作表/修订版

7.添加新的修订版本。

8.关闭对话框。

9.确认现在已进行保存。

10.点击“添加-ins->UI->删除修订版本监视器”按钮以停用监视器。

完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码

PostCommandRevisionMonitor.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.

//
// AUTODESK PROVIDES THIS PROGRAM 'AS IS' AND WITH ALL ITS FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.UI.Events;

namespace Revit.SDK.Samples.PostCommandWorkflow.CS
{
/// <summary>
/// This class has the capabilities to monitor when a document is saved, and prompt the user to
/// add a revision before save takes place.
/// </summary>
class PostCommandRevisionMonitor
{
/// <summary>
/// Constructs a new revision monitor for the given document.
/// </summary>
/// <param name="doc">The document.</param>
public PostCommandRevisionMonitor(Document doc)
{
document = doc;
}

/// <summary>
/// Activates the revision monitor for the stored document.
/// </summary>
public void Activate()
{
// Save the number of revisions as an initial count.
storedRevisionCount = GetRevisionCount(document);

// Setup event for saving.
document.DocumentSaving += OnSavingPromptForRevisions;
}

/// <summary>
/// Deactivates the revision monitor for the stored document.
/// </summary>
public void Deactivate()
{
// Remove the event for saving.
document.DocumentSaving -= OnSavingPromptForRevisions;
}

#region RevitAPI event callbacks

/// <summary>
/// The DocumentSaving callback. This callback checks if at least one new revision has been added, and if not
/// shows instructions to the user to deal with the situation.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void OnSavingPromptForRevisions(object sender, DocumentSavingEventArgs args)
{
Document doc = (Document)sender;
UIApplication uiApp = new UIDocument(doc).Application;

if (doc.IsModified)
{
// Compare number of revisions with saved count
int revisionCount = GetRevisionCount(doc);
if (revisionCount <= storedRevisionCount)
{
// Show dialog with explanation and options
TaskDialog td = new TaskDialog("Revisions not created.");
td.MainIcon = TaskDialogIcon.TaskDialogIconWarning;
td.MainInstruction = "Changes have been made to this document, but no new revision has been created.";
td.ExpandedContent = "Because the document has been released, it is typically required to issue a new " +
"revision number with any change.";
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "Add revision now");
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, "Cancel save");
td.AddCommandLink(TaskDialogCommandLinkId.CommandLink3, "Proceed with save (not recommended).");
td.TitleAutoPrefix = false;
td.AllowCancellation = false;
TaskDialogResult result = td.Show();

switch (result)
{
case TaskDialogResult.CommandLink1: // Add revision now
{
// cancel first save
args.Cancel();

// add event to hide the default "Document not saved" dialog
uiApp.DialogBoxShowing += HideDocumentNotSaved;

// post command for editing revisions
PromptToEditRevisionsAndResave(uiApp);
break;
}
case TaskDialogResult.CommandLink2: // Cancel save
{
// cancel saving only
args.Cancel();
break;
}
case TaskDialogResult.CommandLink3: // Proceed with save
{
// do nothing
break;
}
}
}
else
{
storedRevisionCount = revisionCount;
}
}
}

/// <summary>
/// The DialogBoxShowing callback to cancel display of the "Document not saved" message when saving is cancelled.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void HideDocumentNotSaved(object sender, DialogBoxShowingEventArgs args)
{
TaskDialogShowingEventArgs tdArgs = args as TaskDialogShowingEventArgs;
// The "Document not saved" dialog does not have a usable id, so we are forced to look at the text instead.
if (tdArgs != null && tdArgs.Message.Contains("not saved"))
args.OverrideResult(0x0008);
}

/// <summary>
/// The BeforeExecuted callback for the command, to setup the post action after the revision command is run.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void ReactToRevisionsAndSchedulesCommand(object sender, BeforeExecutedEventArgs args)
{
if (externalEvent != null)
externalEvent.Raise();
}

/// <summary>
/// The external event raised to finalize the workflow after the user has been prompted to enter the
/// Sheet Revisions/Issues command.
/// </summary>
class PostCommandRevisionMonitorEvent : IExternalEventHandler
{
#region IExternalEventHandler Members

/// <summary>
/// The external event callback to finalize the workflow.
/// </summary>
/// <param name="app"></param>
public void Execute(UIApplication app)
{
monitor.CleanupAfterRevisionEdit(app);
}

/// <summary>
/// The external event name.
/// </summary>
/// <returns></returns>
public string GetName()
{
return "PostCommandRevisionMonitorEvent";
}

/// <summary>
/// The constructor for the event instance.
/// </summary>
/// <param name="monitor">The instance of the command.</param>
public PostCommandRevisionMonitorEvent(PostCommandRevisionMonitor monitor)
{
this.monitor = monitor;
}

/// <summary>
/// Handle to the revision monitor.
/// </summary>
private PostCommandRevisionMonitor monitor;

#endregion
}

#endregion

/// <summary>
/// Prompts to edit the revision and resave.
/// </summary>
/// <param name="application"></param>
private void PromptToEditRevisionsAndResave(UIApplication application)
{
// Setup external event to be notified when activity is done
externalEvent = ExternalEvent.Create(new PostCommandRevisionMonitorEvent(this));

// Setup event to be notified when revisions command starts (this is a good place to raise this external event)
RevitCommandId id = RevitCommandId.LookupPostableCommandId(PostableCommand.SheetIssuesOrRevisions);
if (binding == null)
{
binding = application.CreateAddInCommandBinding(id);
}
binding.BeforeExecuted += ReactToRevisionsAndSchedulesCommand;

// Post the revision editing command
application.PostCommand(id);
}

/// <summary>
/// The function that is called to finish the execution of the workflow. Cleans up subscribed events,
/// and posts the save command.
/// </summary>
/// <param name="uiApp"></param>
private void CleanupAfterRevisionEdit(UIApplication uiApp)
{
// Remove dialog box showing
uiApp.DialogBoxShowing -= HideDocumentNotSaved;

if (binding != null)
binding.BeforeExecuted -= ReactToRevisionsAndSchedulesCommand;
externalEvent = null;

// Repost the save command
uiApp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.Save));
}

/// <summary>
/// Storage to remember the number of revisions when last checked.
/// </summary>
private int storedRevisionCount = 0;

/// <summary>
/// The handle to the external event instance to be invoked after the revision editing completes.
/// </summary>
private Autodesk.Revit.UI.ExternalEvent externalEvent = null;

/// <summary>
/// The binding to the revision command.
/// </summary>
private AddInCommandBinding binding = null;

/// <summary>
/// The document.
/// </summary>
private Document document;

/// <summary>
/// Counts the number of revision elements in the document.
/// </summary>
/// <param name="doc">The document.</param>
/// <returns>The number of elements found.</returns>
private static int GetRevisionCount(Document doc)
{
// Find revision objects
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfCategory(BuiltInCategory.OST_Revisions);
return collector.ToElementIds().Count;
}
}
}

PostCommandRevisionMonitorCommand.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM 'AS IS' AND WITH ALL ITS FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable. 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
namespace Revit.SDK.Samples.PostCommandWorkflow.CS
{
    /// <summary>
    /// The external command to set up the revision monitor and execute tasks related to it.
    /// </summary>
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class PostCommandRevisionMonitorCommand : IExternalCommand
    {
        #region IExternalCommand Members
        /// <summary>
        /// The external command callback.
        /// </summary>
        /// <param name="commandData"></param>
        /// <param name="message"></param>
        /// <param name="elements"></param>
        /// <returns></returns>
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            Document doc = commandData.Application.ActiveUIDocument.Document;
            if (monitor == null)
            {
                monitor = new PostCommandRevisionMonitor(doc);
                monitor.Activate();
                commandButton.ItemText = "Remove Revision Monitor";
            }
            else
            { 
                monitor.Deactivate();
                monitor = null;
                commandButton.ItemText = "Setup Revision Monitor";
            }
            return Result.Succeeded;
        }
        #endregion
        /// <summary>
        /// Sets the handle to the command's pushbutton.
        /// </summary>
        /// <param name="pushButton"></param>
        public static void SetPushButton(PushButton pushButton)
        {
            commandButton = pushButton;
        }
        /// <summary>
        /// The monitor.
        /// </summary>
        private static PostCommandRevisionMonitor monitor = null;
        /// <summary>
        /// The handle to the command's PushButton.
        /// </summary>
        private static PushButton commandButton;
    }
       
}