◀ 11.

Revit API の TaskDialog で「はい/いいえ/キャンセル」を分岐する

▶

この記事の要点

  • Revit アドインで確認ダイアログを出すには Autodesk.Revit.UI.TaskDialog を使う
  • 3 つのボタンは TaskDialogCommonButtons(Flags 列挙型)を Yes | No | Cancel のようにビット OR で組み合わせて指定する
  • 押されたボタンは TaskDialogResult で返る。ESC・Alt+F4・× ボタンで閉じた場合も Cancel になる
  • 手軽なのは静的メソッド TaskDialog.Show、本文・詳細・CommandLink まで使うならインスタンスを作って Show()

この記事は Revit API リファレンス(rvtdocs.com に掲載された Revit 2020〜2027 版、2026-10 時点で参照)に記載されているクラス・メンバーだけを使って書いています。ここで扱う TaskDialog のメンバー、TaskDialogCommonButtons・TaskDialogResult・TaskDialogIcon の値は、2020・2022・2025・2027 の各版で同じ構成であることを確認しています。それより古い版を使う場合は、お使いの版の API リファレンスで確認してください。

1TaskDialog とは

Revit API リファレンスでは、TaskDialog(名前空間 Autodesk.Revit.UI、APIObject を継承)は「情報を表示し、ユーザーから簡単な入力を受け取るためのダイアログボックス」と説明されています。共通のコントロールが決まった順序で並ぶので、Revit 本体のダイアログと見た目がそろいます。RevitAPIUI.dll に含まれるクラスなので、アドインのプロジェクトでこの DLL を参照しておく必要があります(参照方法は RevitAPI.dll と RevitAPIUI.dll の参照 を参照)。

ダイアログの表示方法は 2 通りあります。

  • 静的メソッド TaskDialog.Show(...) … 生成と表示を 1 行で行う。指定できるのはタイトル・メイン指示・ボタン・既定ボタンだけ
  • インスタンスを作って Show() … new TaskDialog("タイトル") でオブジェクトを作り、プロパティを個別に設定してから表示する。メインコンテンツ・詳細・CommandLink・チェックボックスなども使える

どちらも戻り値は TaskDialogResult で、これを見て処理を分岐します。

参考画像

旧版の記事から引き継いだ画面例。日本語版 Revit では「はい(Y)」「いいえ(N)」「キャンセル」と表示されている。本文は 3 章のサンプルの文言と同じ内容。

2ボタンと戻り値の対応

TaskDialogCommonButtons は [Flags] 属性付きの列挙型で、複数の値を | で組み合わせて 1 つのダイアログに複数のボタンを並べられます。押されたボタンは同名の TaskDialogResult の値として返ります。

TaskDialogCommonButtonsボタン押されたときの TaskDialogResult
None共通ボタンなし—
OkOKOk
YesはいYes
NoいいえNo
CancelキャンセルCancel(ESC・Alt+F4・× ボタンで閉じた場合も同じ)
Retry再試行Retry
Close閉じるClose

TaskDialogResult にはこのほか、何も返らなかったことを表す None と、CommandLink 用の CommandLink1〜CommandLink4 があり、全部で 11 個の値です。

リファレンスの CommonButtons プロパティの説明には、Revit のダイアログの約束事として次のことが書かれています。

  • 共通ボタンも CommandLink も追加しなかった場合は、「閉じる」ボタンが自動で表示される
  • 情報を伝えるだけのメッセージでは、OK ボタン 1 つではなく「閉じる」ボタン 1 つを使う
  • メイン指示の最後を質問文にして、OK/キャンセルではなくはい/いいえ(または はい/いいえ/キャンセル)を使う
  • よほどの理由がない限りボタン名をカスタマイズしない

つまり「保存しますか?」のような確認は、Revit の流儀でも Yes/No/Cancel の組み合わせが推奨されています。

3静的メソッドで 3 択を出して分岐する

静的な Show には次の 3 つのオーバーロードがあります(インスタンス版の Show() と合わせて 4 つ)。

シグネチャ内容
Show(string title, string mainInstruction)タイトル・メイン指示と「閉じる」ボタン
Show(string title, string mainInstruction, TaskDialogCommonButtons buttons)ボタンを指定
Show(string title, string mainInstruction, TaskDialogCommonButtons buttons, TaskDialogResult defaultButton)ボタンと既定ボタンを指定

いずれも戻り値は TaskDialogResult です。次の外部コマンドは「はい / いいえ / キャンセル」を表示し、押されたボタンに応じてコマンドの戻り値(Autodesk.Revit.UI.Result の Succeeded / Failed / Cancelled)を変えます。外部コマンドの作り方そのものは Revit API:外部コマンド/アプリ を参照してください。

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

[Transaction(TransactionMode.Manual)]
public class YesNoCancelCommand : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        TaskDialogResult res = TaskDialog.Show(
            "TestTool",
            "Click Yes to return Succeeded.\nClick No to return Failed.\nClick Cancel to return Cancelled.",
            TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No | TaskDialogCommonButtons.Cancel);

        switch (res)
        {
            case TaskDialogResult.Yes:
                return Result.Succeeded;
            case TaskDialogResult.No:
                message = "「いいえ」が選ばれました。";
                return Result.Failed;
            default:
                // Cancel のほか、ESC・Alt+F4・× で閉じた場合もここに来る
                return Result.Cancelled;
        }
    }
}

ポイントは次のとおりです。

  • ボタンの組み合わせは TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No | TaskDialogCommonButtons.Cancel のように OR でつなぐ
  • Cancel は「キャンセル」ボタンだけでなく、ESC キー・Alt+F4・× ボタンで閉じたときにも返る。上の例のように default で受けておくと取りこぼしがない
  • Execute の message に入れた文字列は、戻り値が Failed のときだけ表示される(1023 文字を超えると切り詰められる)。Failed や Cancelled を返すと、そのコマンドが行ったモデルへの変更は Revit が取り消す
  • メイン指示の改行には \n が使える(段落を空けるなら \n\n)。一方、タイトルには改行を入れられない

エラーを伝えるだけのダイアログ(ボタンが「閉じる」だけのもの)は エラーメッセージの設定方法 で扱っています。

既定ボタンを「いいえ」にする

削除のように取り消しにくい操作の確認では、Enter キーをうっかり押しても実行されないよう、既定ボタンを「いいえ」にしておけます。4 引数版の Show の最後に既定にしたいボタンの TaskDialogResult を渡します。

TaskDialogResult res = TaskDialog.Show(
    "要素の削除",
    "選択した要素を削除しますか?",
    TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No | TaskDialogCommonButtons.Cancel,
    TaskDialogResult.No);   // 既定ボタン

リファレンスによると、既定ボタンに TaskDialogResult.None を渡した場合や、ダイアログに存在しないボタンの値を渡した場合は、ダイアログの最初のボタンが既定になります。

4インスタンスを作って細かく設定する

静的メソッドではタイトルとメイン指示しか書けません。補足説明や詳細情報を付けたい場合は、TaskDialog のインスタンスを作り、プロパティを設定してからインスタンスメソッドの Show() を呼びます。

メンバー内容(リファレンスの説明)
TaskDialog(string title)タイトルを指定して作成。null や空文字は例外になる
Titleタイトル。改行不可。表示時は既定で外部コマンド名などが先頭に付く
TitleAutoPrefixタイトルに先頭の名前を自動で付けるか。既定値は true
MainInstructionダイアログ上部の大きな主文。状況を簡潔にまとめ、3 行以内が目安
MainContent主文の下に小さく表示する補足説明(省略可)
ExpandedContent既定では隠れていて、表示/非表示の切り替えボタンで開く詳細欄
FooterTextフッター欄の文字列。HTML のハイパーリンクタグが使える
CommonButtons表示する共通ボタン(TaskDialogCommonButtons)
DefaultButton既定ボタン(TaskDialogResult)
MainIconアイコン(TaskDialogIcon)。既定はアイコンなし
AllowCancellationキャンセルボタンがないときに閉じる操作でキャンセルできるか。既定値は true
VerificationText確認用チェックボックスのラベル。状態は WasVerificationChecked() で取得
AddCommandLink(...)CommandLink(大きな選択肢ボタン)を追加
string familyPath = @"C:\Families\Door.rfa";  // 例: 読み込もうとしているファイル
TaskDialog dlg = new TaskDialog("ファミリの上書き");
dlg.MainInstruction = "同じ名前のファミリが既に読み込まれています。上書きしますか?";
dlg.MainContent = "「いいえ」を選ぶと既存のファミリをそのまま使います。";
dlg.ExpandedContent = "対象ファイル: " + familyPath;
dlg.CommonButtons = TaskDialogCommonButtons.Yes
                  | TaskDialogCommonButtons.No
                  | TaskDialogCommonButtons.Cancel;
dlg.DefaultButton = TaskDialogResult.No;
dlg.VerificationText = "残りのファイルにも同じ選択を適用する";

TaskDialogResult res = dlg.Show();
bool applyToAll = dlg.WasVerificationChecked();

if (res == TaskDialogResult.Yes)
{
    // 上書きする処理
}
else if (res == TaskDialogResult.No)
{
    // 既存を使う処理
}
else
{
    // Cancel(ESC・× を含む): 処理全体を中止
}

WasVerificationChecked() は、チェックボックスを持たないダイアログや、まだ表示していないダイアログで呼ぶと InvalidOperationException になります。必ず Show() の後で呼んでください。

アイコンについて

TaskDialogIcon の値は TaskDialogIconNone / TaskDialogIconShield / TaskDialogIconInformation / TaskDialogIconError / TaskDialogIconWarning の 5 つです。ただしリファレンスの MainIcon の説明では、Revit のダイアログは見た目を煩雑にしないためアイコンをほとんど使わず、使うのは警告(!)アイコンだけ、それもデータの消失や大きな時間のロスにつながる場合に限る、とされています。

5CommandLink で選択肢を出す

「はい / いいえ」では意味が伝わりにくい選択(たとえば「上書き」「別名で保存」)は、ボタンではなく CommandLink にすると、選択肢ごとに説明文を付けられます。AddCommandLink には ID とメイン文だけを渡す版と、補足文も渡す版があります。ID は TaskDialogCommandLinkId.CommandLink1〜CommandLink4 の 4 つで、選ばれると同じ番号の TaskDialogResult.CommandLink1〜CommandLink4 が返ります。

TaskDialog dlg = new TaskDialog("書き出し先の確認");
dlg.MainInstruction = "同じ名前のファイルがあります。どうしますか?";
dlg.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "上書きする", "既存のファイルは置き換えられます。");
dlg.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, "別の名前で保存する");
dlg.CommonButtons = TaskDialogCommonButtons.Cancel;

switch (dlg.Show())
{
    case TaskDialogResult.CommandLink1:
        // 上書き
        break;
    case TaskDialogResult.CommandLink2:
        // 別名で保存
        break;
    default:
        // Cancel
        break;
}

リファレンスに書かれている CommandLink の注意点は次のとおりです。

  • メイン文(mainContent)に改行は入れられない。null・空文字・改行を含む文字列は例外になる
  • 同じ ID で再度追加すると、後の定義で上書きされる
  • 表示順は追加した順ではなく、ID の番号順
  • CommandLink を並べるときは、メイン指示の最後を「どうしますか?」(リファレンスの例では "What do you want to do?")とするのが標準

6確認してからモデルを変更する

実際のアドインでは「はい」が選ばれたときだけモデルを変更する、という使い方が多くなります。TransactionMode.Manual の外部コマンドでは、ダイアログで確認してからトランザクションを開始すれば、「いいえ」や「キャンセル」のときには何も変更しないまま終われます。トランザクションの基本は Revit API:トランザクションと要素編集 を参照してください。

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    UIDocument uidoc = commandData.Application.ActiveUIDocument;
    Document doc = uidoc.Document;
    ICollection<ElementId> ids = uidoc.Selection.GetElementIds();

    if (ids.Count == 0)
    {
        TaskDialog.Show("要素の削除", "要素が選択されていません。");
        return Result.Cancelled;
    }

    TaskDialogResult res = TaskDialog.Show(
        "要素の削除",
        ids.Count + " 個の要素を削除しますか?",
        TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No | TaskDialogCommonButtons.Cancel,
        TaskDialogResult.No);

    if (res != TaskDialogResult.Yes)
    {
        return Result.Cancelled;   // いいえ / キャンセル / × は何もしない
    }

    using (Transaction tx = new Transaction(doc, "選択要素の削除"))
    {
        tx.Start();
        doc.Delete(ids);
        tx.Commit();
    }
    return Result.Succeeded;
}

この例では「いいえ」と「キャンセル」を同じ扱いにしていますが、3 択にする意味があるのは、たとえば複数ファイルを順に処理するときに「はい=この 1 件を処理」「いいえ=この 1 件だけ飛ばす」「キャンセル=ループ全体を中止」のように、いいえとキャンセルで動作を変えたい場合です。上の例のように「はい以外は中止」で十分なら、Yes | No の 2 択にした方が迷わせません。

7注意点

  • Revit のメインスレッドから表示する: インスタンス版 Show() は、Revit のメインスレッド以外から呼ぶと InvalidOperationException になります。外部コマンドの Execute の中など、Revit から呼ばれた API コンテキストで表示してください。
  • 2 種類のチェックボックスは同時に使えない: VerificationText の確認用チェックボックスと ExtraCheckBoxText の追加チェックボックスを同時に有効にすると、Show() で InvalidOperationException になります。
  • タイトルの先頭に名前が付く: 表示時、タイトルの先頭には既定で外部コマンド名(または外部アプリケーション名)が付きます。不要なら TitleAutoPrefix = false にします。リファレンスでは、タイトルはダイアログごとに固有にし、「なぜこのメッセージが出たのか」を表すものにするよう勧めています。
  • × ボタンも Cancel: 「キャンセル」ボタンを置かなくても、AllowCancellation が既定の true なら ESC や × で閉じられ、そのときは TaskDialogResult.Cancel が返ります。分岐では Yes / No 以外をすべて想定しておくのが安全です。

8関連

子ページ

子ページはありません

同階層のページ
  1. RevitAPI.dll と RevitAPIUI.dll の参照
  2. マニフェストファイルの書き方
  3. アドインの追加/設置方法
  4. アドインの作成サンプル(外部ツール編)
  5. アドインの作成サンプル(外部アプリケーション編)
  6. 要素の取得と情報の表示
  7. 要素のカテゴリとマテリアルの取得と表示
  8. よく使うBuiltInCategoryの一覧
  9. 外部ツールでAutodesk.Revit.Documentを取得する方法
  10. エラーメッセージの設定方法
  11. 「はい」、「いいえ」、「キャンセル」ボタンの設置と処理分岐
  12. 要素(カテゴリ、ファミリ、タイプ)とは
  13. ElementIdとUniqueIdの違い
  14. 要素フィルターの使い方
  15. 要素のパラメータ一覧の取得
  16. pyRevitの導入と簡単なアプリケーションの作成
  17. Revit SDKのサンプルの場所とビルド方法
  18. FamilySymbol(タイプ)の取得とパラメータの変更
  19. 相対パスでdllにアイコン画像を埋め込む方法
  20. 「グループ」について

最近更新/作成されたページ