カスタム UI の組み込み
プレビュー公開
本機能および本機能で利用する API は先行公開しているものです。 現時点で品質保証しておりませんので、ご利用される場合はユーザー様の責任でご利用ください。 また、これらの仕様は予告なく変更する場合がありますのでご了承ください。
概要
Next Design に標準搭載されている UI 以外に、ユーザーが独自に開発した UI を次の部分に組み込んでモデル編集機能を拡張できます。
- モデルエディタのビュー
- ナビゲータ
- インスペクタ
カスタム UI を Next Design に組み込む方法を説明します。カスタム UI を組み込む場合は、マニフェストでの拡張ポイントの定義は不要です。代わりにメインクラスで IExtension を実装する際に、処理を追加する必要があります。カスタム UI の ViewModel クラスを Next Design の API と結合することで、 カスタム UI で Next Design のモデルを表示・編集できます。
カスタム UI を組み込むには次の実装と手順が必要です。
- カスタム UI インタフェースの実装
- カスタム UI 登録処理と登録解除処理の実装
- カスタム UI のビュー追加
tip
カスタム UI は、MVVM モデル(Model-View-ViewModel)のアーキテクチャに従っている必要があります。
カスタム UI インタフェースの実装
ViewModel クラスで、UI の種類に応じてインターフェスを実装します。
UI の種類と実装するインターフェース
UI 種類 ViewModel で実装するインターフェース 実装が必要なプロパティ/メソッド カスタムエディタ ICustomEditorView Descriptor プロパティ
OnInitialized メソッド
OnBeforeDispose メソッド
ViewDefinitionId プロパティ
SelectedItem プロパティ
SelectedItems プロパティ
SetModel メソッド
GetDocumentContent メソッド(※)カスタムナビゲータ ICustomNavigator Descriptor プロパティ
OnInitialized メソッド
OnBeforeDispose メソッド
SelectedItem プロパティ
SelectedItems プロパティ
IsEnabled メソッド
OnShow メソッド
OnHide メソッドカスタムインスペクタ ICustomInspector Descriptor プロパティ
OnInitialized メソッド
OnBeforeDispose メソッド
SetModel メソッド
上記のインターフェースを実装することで、Next Design のモデルと ViewModel クラスを繋ぐことができます。詳細は各 API 仕様をご参照ください。
note
(※)GetDocumentContent メソッドは、将来の機能拡張のために用意した API です。現行バージョンでは、null を返すのみとしてください。
カスタム UI 登録処理と登録解除処理の実装
IExtention を実装したメインクラスの公開メソッド Activate
にカスタム UI の登録処理を実装します。そして、メインクラスの公開メソッド Deactviate
にカスタム UI の登録解除処理を実装します。
Activate
メソッド : カスタム UI の登録
Deactivate
メソッド : カスタム UI の登録解除
登録処理に使用するAPI
対象 コールバック関数の登録 API カスタムエディタ RegisterCustomEditor カスタムナビゲータ RegisterCustomNavigator カスタムインスペクタ RegisterCustomInspector
実装例
CustomUISampleEntryPoint クラスで IExtension インタフェースを実装する場合の例を示します。 View の実装が SampleCustomEditor クラス, ViewModel の実装が SampleCustomEditorViewModel クラスとします。
IExtension の実装例
public class CustomUISampleEntryPoint : IExtension
{
/// <summary>
/// エクステンション活性化時の処理
/// </summary>
/// <param name="context"></param>
public void Activate(IContext context)
{
var registry = context.App.CustomUI;
var extensionName = context.ExtensionInfo.Name;
// 実装したViewModelとViewを登録
// 実装したUIの種類に応じたメソッドを呼び出し
registry.RegisterCustomEditor<SampleCustomEditorViewModel, SampleCustomEditor>(extensionName, SampleCustomEditorViewModel.Descriptor);
}
/// <summary>
/// エクステンション非活性化時の処理
/// </summary>
/// <param name="context"></param>
public void Deactivate(IContext context)
{
var registry = context.App.CustomUI;
var extensionName = context.ExtensionInfo.Name;
// カスタム UI の登録解除
registry.UnRegisterAllCustomUIs(extensionName);
}
}
カスタム UI のビュー追加
組み込むカスタム UI の種類がエディタの場合は、対象モデルのビューにカスタム UI を追加します。
- モデルナビゲータで カスタム UI の対象モデルを選択します。
- コンテキストメニューの [ビューの追加] を実行します。
- 組み込んだカスタム UI のエディタ名を選択し、ビューを追加します。
- 追加されたビューに切り替えると、組み込んだカスタム UI で対象モデルを表示・編集できます。
サンプル:カスタムエディタ/インスペクタ/ナビゲータの追加
カスタム UI のサンプルとして、Next Design に標準で組み込まれている UI とは表示内容の異なるカスタムエディタ/インスペクタ/ナビゲータを追加します。 以下では、Visual Studio プロジェクトの新規作成から、実際にカスタム UI を組み込むところまでを説明します。
全体の流れ
- Visual Studio プロジェクトの新規作成
- View クラス、ViewModel クラスの追加
- ViewModel クラスでのカスタム UI インタフェースの実装
- カスタム UI 登録処理と登録解除処理の実装
- View クラスでの UI の実装
- カスタムエディタのビュー追加
公開サンプル
以下の手順で作成されるサンプルのソースコード一式を GitHub で公開しています。
外部リンク: CustomUISample
ゴールイメージ
- ナビゲーターにカスタムナビゲータが追加され、独自の UI でモデルを選択できます。
- ビューの種類にカスタムエディタが追加され、モデルエディタのビューをカスタムエディタに切り替えて、独自の UI でモデルを表示・編集できます。
- インスペクタのタブにカスタムインスペクタが追加され、独自の UI で編集対象のモデルに関する詳細情報を表示・編集できます。
Visual Studio プロジェクトの新規作成
カスタム UI の開発では、プロジェクト新規作成時にプロジェクトの種類として [WPF クラスライブラリ] を選択します。これによりユーザーコントロールを配置できるようになります。
プロジェクト新規作成時の以下の設定は、チュートリアル > モデル一括検証と同様です。
- エクステンション開発用 DLL のコピー
- エクステンション開発用 DLL の参照設定追加
- デバッグ実行準備の自動化
マニフェストを新規作成し、定義します。 以下は、チュートリアル > モデル一括検証 と同様です。
- 実行プログラムのエントリーポイント定義
- エクステンションのライフサイクル定義
- エクステンションの対象プロファイル指定
カスタムUI の実現では、マニフェストに以下の定義は不要です。
- UI の拡張ポイント定義(リボンタブ・グループ・ボタン)
- コマンドの拡張ポイント定義
実装コード
manifest.json
{
// エクステンション定義
"name": "DensoCreate.NextDesign.Extensions.CustomUISample",
"version": "1.0.0",
"publisher": "DENSO CREATE Inc.",
"license": "Next Design 使用許諾契約書に準ずる。Copyright (C) 2021 DENSO CREATE INC. All rights reserved.",
"main": "CustomUISample.dll", // エントリーポイントとしてビルド結果の DLL ファイル名を指定します。
"lifecycle": "application", // ライフサイクルとしてアプリケーションライフサイクルを指定します。
"baseProfile": "" // プロファイル名の条件を指定しません。
}
View クラス、ViewModel クラスの追加
カスタムエディタ、カスタムナビゲータ、カスタムインスペクタに必要な View クラスと ViewModel クラスを Visual Studio プロジェクトに追加します。 今回追加するクラス名は次の通りです。
追加する UI 種類 | View クラス | ViewModel クラス |
---|---|---|
カスタムエディタ | CustomEditor | CustomEditorViewModel |
カスタムナビゲータ | CustomNavigator | CustomNavigatorViewModel, CustomNavigatorItemViewModel(※) |
カスタムインスペクタ | CustomInspector | CustomInspectorViewModel |
(※) CustomNavigatorItemViewModel は、カスタムナビゲータ内に表示する表示要素のクラスです。
View クラス
Visual Studio のソリューションエクスプローラーで、プロジェクトに新しい項目としてユーザーコントロール(WPF)を選択します。
ViewModel クラス
Visual Studio のソリューションエクスプローラーで、プロジェクトに新しい項目としてクラスを追加します。
上記を追加した Visual Studio のプロジェクトの構成を以下にします。
CustomUISample/
CustomUISample.sln
CustomUISample/
CustomUISample.csproj
manifest.json
View/
Editor/
CustomEditor.xaml
CustomEditor.xaml.cs
Inspector/
CustomInspector.xaml
CustomInspector.xaml.cs
Navigator
CustomNavigator.xaml
CustomNavigator.xaml.cs
ViewModel/
Editor/
CustomEditorViewModel.cs
Inspector/
CustomInspectorViewModel.cs
Navigator
CustomNavigatorViewModel.cs
CustomUISampleEntryPoint.cs(※)
※CustomUISampleEntryPoint は、IExtension のインターフェースを実装するメインクラスです。
ViewModel クラスでのカスタム UI インタフェースの実装
ViewModel クラスで、UI の種類に応じて次のインターフェースを実装します。
追加する UI 種類 | ViewModel で実装するインターフェース | 実装が必要なプロパティ/メソッド |
---|---|---|
カスタムエディタ | ICustomEditorView | ViewDefinitionId プロパティ SelectedItem プロパティ SelectedItems プロパティ SetModel メソッド GetDocumentContent メソッド |
カスタムナビゲータ | ICustomNavigator | SelectedItem プロパティ SelectedItems プロパティ IsEnabled メソッド OnShow メソッド OnHide メソッド |
カスタムインスペクタ | ICustomInspector | SetModel メソッド |
実装コード
カスタムエディタ
カスタムエディタの ViewModel クラスで ICustomEditorView を実装します。
CustomEditorViewModel.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using NextDesign.Core;
using NextDesign.Desktop;
using NextDesign.Desktop.CustomUI;
using NextDesign.Extension;
namespace CustomUISample.ViewModel.Editor
{
class CustomEditorViewModel : ICustomEditorView
{
#region タイプ記述子
/// <summary>
/// タイプ記述子
/// </summary>
private static CustomEditorDefinitionDescriptor s_DefinitionDescriptor;
/// <summary>
/// タイプ記述子
/// </summary>
public static CustomEditorDefinitionDescriptor DefinitionDescriptor
{
get
{
return s_DefinitionDescriptor ?? (s_DefinitionDescriptor = new CustomEditorDefinitionDescriptor
{
// カスタムエディタの種類識別子
CustomEditorTypeId = "CustomUI.Test",
// アクセスキー
AccessKey = "P",
// 表示名
DisplayName = "カスタムエディタ",
// グループ名
GroupName = "カスタムエディタ",
// アイコン(大)pack - uri 形式の文字列、または Stream 型を指定できます。
LargeIcon =
"pack://application:,,,/CustomUISample;component/Resources/Images/TestEditor32.png",
// アイコン(小)pack - uri 形式の文字列、または Stream 型を指定できます。
SmallIcon =
"pack://application:,,,/CustomUISample;component/Resources/Images/TestEditor16.png"
});
}
}
#endregion
#region プロパティ
/// <summary>
/// タイプ記述子
/// </summary>
public ICustomDescriptor Descriptor { get; set; }
/// <summary>
/// 対応するビュー定義のId
/// </summary>
public string ViewDefinitionId => Editor?.EditorDefinition.Id;
/// <summary>
/// エディタで選択された要素
/// 選択された要素がない場合は、null を返すように実装してください。
/// </summary>
public object SelectedItem => null;
/// <summary>
/// エディタで選択された要素の列挙
/// 選択された要素がない場合は、空の列挙を返すように実装してください。
/// </summary>
public IEnumerable<object> SelectedItems => Enumerable.Empty<object>();
/// <summary>
/// アプリケーション
/// </summary>
public IApplication App { get; private set; }
/// <summary>
/// エクステンション
/// </summary>
public CustomUISampleEntryPoint Extension { get; private set; }
/// <summary>
/// エディタ情報
/// </summary>
public ICustomEditor Editor { get; private set; }
/// <summary>
/// 対象モデル
/// </summary>
public IModel TargetModel { get; private set; }
#endregion
#region イベントハンドラ
/// <summary>
/// 独自拡張するユーザインタフェースを初期化する際の処理
/// Next Designは、独自拡張するユーザインタフェースを初期化する際にこのメソッドを呼び出します。
/// 拡張側で初期化時に実行したい処理がある場合はここで実装します。
/// </summary>
/// <param name="args"></param>
public void OnInitialized(InitializedEventArgs args)
{
// アプリケーションとエクステンションの情報を記憶します
App = args.App;
Extension = args.Extension as CustomUISampleEntryPoint;
}
/// <summary>
/// 独自拡張するユーザインタフェースを破棄する前の処理
/// Next Designは、独自拡張するユーザインタフェースを破棄する前にこのメソッドを呼び出します。
/// 拡張側で破棄前に実行したい処理がある場合はここで実装します。
/// </summary>
/// <param name="args"></param>
public void OnBeforeDispose(BeforeDisposeEventArgs args)
{
// 破棄する前の処理なし
}
#endregion
#region インターフェース実装
/// <summary>
/// このエディタの表示対象のモデルを設定します。
/// </summary>
/// <param name="model"></param>
public void SetModel(ICustomEditor model)
{
Editor = model;
TargetModel = model.Model;
}
/// <summary>
/// ドキュメント出力するコンテンツの内容を取得します。
/// </summary>
/// <param name="context"></param>
public ICustomEditorDocumentContent GetDocumentContent(ICustomEditorDocumentGenerationContext context)
{
// 現行バージョンでは、null 固定とします
return null;
}
#endregion
}
}
カスタムインスペクタ
CustomInspectorViewModel.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using NextDesign.Core;
using NextDesign.Desktop.CustomUI;
namespace CustomUISample.ViewModel.Inspector
{
class CustomInspectorViewModel : ICustomInspector
{
#region フィールド
/// <summary>
/// ターゲットモデル
/// </summary>
private object m_Object;
#endregion
#region プロパティ
/// <summary>
/// タイプ記述子
/// </summary>
public ICustomDescriptor Descriptor { get; set; }
/// <summary>
/// 名前
/// </summary>
public string Name
{
get
{
if (m_Object is IModel model)
{
return $"{model.Name}({model.GetType().Name})";
}
return m_Object?.GetType().Name;
}
}
#endregion
#region イベントハンドラ
/// <summary>
/// 初期化
/// </summary>
/// <param name="args">イベントパラメータ</param>
public void OnInitialized(InitializedEventArgs args)
{
// 独自拡張するユーザインタフェースを初期化する際の処理
// Next Designは、独自拡張するユーザインタフェースを初期化する際にこのメソッドを呼び出します。
// 拡張側で初期化時に実行したい処理がある場合はここで実装します。
}
/// <summary>
/// 破棄
/// </summary>
/// <param name="args">イベントパラメータ</param>
public void OnBeforeDispose(BeforeDisposeEventArgs args)
{
// 独自拡張するユーザインタフェースを破棄する前の処理
// Next Designは、独自拡張するユーザインタフェースを破棄する前にこのメソッドを呼び出します。
// 拡張側で破棄前に実行したい処理がある場合はここで実装します。
}
/// <summary>
/// このインスペクタの表示対象のモデルを設定します。
/// </summary>
/// <param name="target">ターゲットのモデル</param>
/// <param name="targets">ターゲットのモデル群</param>
public void SetModel(object target, IEnumerable<object> targets)
{
m_Object = target;
}
#endregion
}
}
カスタムナビゲータ
カスタムナビゲータの ViewModel クラスで ICustomNavigator を実装します。
CustomNavigatorViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Linq;
using NextDesign.Core;
using NextDesign.Desktop;
using NextDesign.Desktop.CustomUI;
namespace CustomUISample.ViewModel.Navigator
{
public class CustomNavigatorViewModel : ICustomNavigator, IDisposable
{
#region プロパティ
/// <summary>
/// タイプ記述子
/// </summary>
public ICustomDescriptor Descriptor { get; set; }
/// <summary>
/// 選択しているアイテム
/// </summary>
private object m_SelectedItem;
/// <summary>
/// 選択しているアイテム
/// </summary>
public object SelectedItem
{
get => m_SelectedItem;
set
{
m_SelectedItem = value;
// 選択しているアイテムが、Modelの場合は
// 現在のワークスペースのカレントモデルとインスペクト対象の要素を設定します。
if (m_SelectedItem is IModel model)
{
Workspace.State.SetCurrentModel(model); ;
Workspace.State.SetInspectedObject(model); ;
}
}
}
/// <summary>
/// エディタで選択された要素の列挙
/// 選択された要素がない場合は、空の列挙を返すように実装してください。
/// </summary>
public IEnumerable<object> SelectedItems => Enumerable.Empty<object>();
/// <summary>
/// ID
/// </summary>
/// <summary>
/// アイテム
/// </summary>
private ObservableCollection<CustomNavigatorItemViewModel> m_Items;
/// <summary>
/// アイテム
/// </summary>
public IEnumerable<CustomNavigatorItemViewModel> Items => m_Items;
/// <summary>
/// ワークスペース
/// </summary>
private IWorkspace Workspace => m_App.Workspace;
#endregion
#region 内部フィールド
/// <summary>
/// コンフィグレーション
/// </summary>
private CustomNavigatorConfigs m_Configs;
/// <summary>
/// アプリケーション
/// </summary>
private NextDesign.Desktop.IApplication m_App;
#endregion
#region 構築・消滅
/// <summary>
/// 破棄
/// </summary>
public void Dispose()
{
DisposeItems();
if (m_App != null)
{
m_App = null;
}
}
/// <summary>
/// アイテムをDisposeする
/// </summary>
public void DisposeItems()
{
if (m_Items == null)
{
return;
}
foreach (var item in m_Items)
{
item.Dispose();
}
m_Items.Clear();
m_Items = null;
}
#endregion
#region イベントハンドラ
/// <summary>
/// OnInitialized "独自拡張するユーザインタフェースを初期化する際の処理
/// Next Designは、独自拡張するユーザインタフェースを初期化する際にこのメソッドを呼び出します。
/// 拡張側で初期化時に実行したい処理がある場合はここで実装します。"
/// </summary>
/// <param name="args"></param>
public void OnInitialized(InitializedEventArgs args)
{
m_Configs = new CustomNavigatorConfigs();
m_Configs.SelectionMode = SelectionMode.Multiple;
}
/// <summary>
/// 独自拡張するユーザインタフェースを破棄する前の処理
/// Next Designは、独自拡張するユーザインタフェースを破棄する前にこのメソッドを呼び出します。
/// 拡張側で破棄前に実行したい処理がある場合はここで実装します。
/// </summary>
/// <param name="args"></param>
public void OnBeforeDispose(BeforeDisposeEventArgs args)
{
// 処理なし
}
/// <summary>
/// このナビゲータを表示する際の処理
/// Next Designは、独自拡張するナビゲータを表示する際にこのメソッドを呼び出します。
/// 拡張側で表示時に実行したい処理がある場合はここで実装します。
/// </summary>
/// <param name="args"></param>
public void OnShow(OnShowEventArgs args)
{
m_App = args.App;
var project = m_App.Workspace.CurrentProject;
CreateChildren(project);
}
/// <summary>
/// このナビゲータを非表示にする際の処理
/// Next Designは、独自拡張するナビゲータを隠す際にこのメソッドを呼び出します。
/// 拡張側で非表示時に実行したい処理がある場合はここで実装します。
/// </summary>
/// <param name="args"></param>
public void OnHide(OnHideEventArgs args)
{
// 処理なし
}
#endregion
#region 内部処理
/// <summary>
/// 子要素を生成
/// </summary>
/// <param name="project"></param>
private void CreateChildren(IProject project)
{
if (project == null)
{
return;
}
// モデルの子要素を取得し、ナビゲータの子要素を生成します
var models = project.GetChildren().OfType<IModel>();
var items = new ObservableCollection<CustomNavigatorItemViewModel>();
foreach (var model in models)
{
var item = new CustomNavigatorItemViewModel(model, this);
items.Add(item);
}
m_Items = items;
}
/// <summary>
/// アイコンを取得する
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
internal object GetIcon(IModel model)
{
if (m_App == null)
{
return null;
}
if (model == null)
{
return null;
}
var icon = m_App.Resources.GetObjectIcon(model);
return icon;
}
#endregion
}
}
カスタムナビゲータに表示する表示要素のクラスを実装します。
CustomNavigatorItemViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Linq;
using NextDesign.Core;
namespace CustomUISample.ViewModel.Navigator
{
/// <summary>
/// サンプルナビゲータのアイテムVM
/// </summary>
public class CustomNavigatorItemViewModel : IDisposable
{
#region 内部フィールド
/// <summary>
/// 子要素
/// </summary>
private ObservableCollection<CustomNavigatorItemViewModel> m_Children;
/// <summary>
/// モデル
/// </summary>
private IModel m_Model;
/// <summary>
/// オーナー
/// </summary>
private CustomNavigatorViewModel m_Owner;
#endregion
#region プロパティ
/// <summary>
/// モデル
/// </summary>
public IModel Model => m_Model;
/// <summary>
/// 子要素
/// </summary>
public IEnumerable<CustomNavigatorItemViewModel> Children => m_Children;
/// <summary>
/// アイコン
/// </summary>
public object Icon => m_Owner?.GetIcon(Model);
#endregion
#region 構築・消滅
/// <summary>
/// コンストラクタ
/// </summary>
public CustomNavigatorItemViewModel(IModel model, CustomNavigatorViewModel owner)
{
m_Model = model;
m_Owner = owner;
CreateChildren();
}
/// <summary>
/// 破棄
/// </summary>
public void Dispose()
{
if (m_Model != null)
{
m_Model = null;
}
if (m_Children != null)
{
foreach (var child in m_Children)
{
child.Dispose();
}
m_Children.Clear();
m_Children = null;
}
}
#endregion
#region 内部処理
/// <summary>
/// 子要素の生成
/// </summary>
private void CreateChildren()
{
var children = m_Model.GetChildren().OfType<IModel>();
if (!children.Any())
{
return;
}
if (m_Children == null)
{
m_Children = new ObservableCollection<CustomNavigatorItemViewModel>();
}
foreach (var child in children)
{
var item = new CustomNavigatorItemViewModel(child, m_Owner);
m_Children.Add(item);
}
}
#endregion
}
}
カスタム UI 登録処理と登録解除処理の実装
IExtention を実装したメインクラスの公開メソッド Activate
にカスタム UI の登録処理を実装します。そして、メインクラスの公開メソッド Deactviate
にカスタム UI の登録解除処理を実装します。
カスタムインスペクタ、カスタムナビゲータの表示位置
カスタムインスペクタ、カスタムナビゲータは、カスタムUI 登録時にdouble 型の値で表示位置を指定します。 Next Design 標準のインスペクタ、ナビゲータには、IDと固有値が割り当てられています。値が小さいほど画面上で左側に表示されますので、特定のインスペクタ、ナビゲータの右隣に表示する場合は、そのインスペクタ、ナビゲータの値 +1 の値を指定するなどしてください。 以下に Next Design 標準のインスペクタ、ナビゲータの表示位置の値を示します。
参考:標準インスペクタの表示位置
インスペクタ ID 値 プロパティ(モデル) CustomInspectorDescriptor.DisplayOrderModel 100 関連(モデル) CustomInspectorDescriptor.DisplayOrderRelationship 200 ダイアグラム定義 CustomInspectorDescriptor.DisplayOrderDiagramDefinition 1000 シェイプ定義(ノード) CustomInspectorDescriptor.DisplayOrderNodeShapeDefinition 1100 シェイプ定義(ポート) CustomInspectorDescriptor.DisplayOrderPortShapeDefinition 1200 シェイプ定義(コネクタ) CustomInspectorDescriptor.DisplayOrderConnectorShapeDefinition 1300 フォーム定義 CustomInspectorDescriptor.CustomInspectorDescriptor 2000 フォーム要素(コントロール) CustomInspectorDescriptor.DisplayOrderFormControlDefinition 2100 フォーム要素(グループ) CustomInspectorDescriptor.DisplayOrderGroupDefinition 2200 フォーム要素(グリッド) CustomInspectorDescriptor.DisplayOrderGridDefinition 2300 フォーム要素(リスト) CustomInspectorDescriptor.DisplayOrderListDefinition 2400 行の定義 CustomInspectorDescriptor.DisplayOrderTreeGridRow 3100 シェイプ定義(ライフライン) CustomInspectorDescriptor.DisplayOrderLifelineShapeDefinition 4100 シェイプ定義(ノート(シーケンス)・複合フラグメント) CustomInspectorDescriptor.DisplayOrderSequenceNodeShapeDefinition 4200 シェイプ定義(メッセージ(シーケンス)) CustomInspectorDescriptor.DisplayOrderMessageShapeDefinition 4300 シェイプ定義(ノートアンカ) CustomInspectorDescriptor.DisplayOrderNoteAnchorShapeDefinition 4400 シェイプ定義(実行仕様・破棄・メッセージ端) CustomInspectorDescriptor.DisplayOrderSequenceShapeDefinition 4500 パッケージ CustomInspectorDescriptor.DisplayOrderPackage 10000 メタモデル(クラス) CustomInspectorDescriptor.DisplayOrderClass 11000 メタモデル(関連クラス) CustomInspectorDescriptor.DisplayOrderRelationshipClass 11100 フィールド CustomInspectorDescriptor.DisplayOrderField 12000 列挙 CustomInspectorDescriptor.DisplayOrderEnum 13000 参考:標準ナビゲータの表示位置
ナビゲータ ID 値 モデルナビゲータ CustomNavigatorDescriptor.DisplayOrderModel 100 プロダクトラインナビゲータ CustomNavigatorDescriptor.DisplayOrderProductLine 200 構成管理ナビゲータ CustomNavigatorDescriptor.DisplayOrderScm 300 プロジェクトナビゲータ CustomNavigatorDescriptor.DisplayOrderProject 400 プロファイルナビゲータ CustomNavigatorDescriptor.DisplayOrderProfile 500
タイプ記述子
カスタムUI を登録する際には、タイプ記述子を指定します。 タイプ記述子では、カスタムUI の静的な情報を定義します。
カスタムUI | タイプ記述子 | 定義する情報 |
---|---|---|
カスタムエディタ | CustomEditorDescriptor | ID CustomEditorDefinitionDescriptor(※) |
カスタムナビゲータ | CustomNavigatorDescriptor | ID 表示名 表示位置 アイコン |
カスタムインスペクタ | CustomInspectorDescriptor | ID 表示名 表示位置 |
※CustomEditorDefinitionDescriptor では、以下の情報を定義します。
- ID
- アクセスキー
- 表示名
- グループ名
- アイコン
実装コード
カスタムエディタ、インスペクタ、ナビゲータの登録処理、登録解除処理を実装します。
CustomUISampleEntryPoint.cs
using System;
using CustomUISample.View.Editor;
using CustomUISample.View.Inspector;
using CustomUISample.View.Navigator;
using CustomUISample.ViewModel.Editor;
using CustomUISample.ViewModel.Inspector;
using CustomUISample.ViewModel.Navigator;
using NextDesign.Extension;
using NextDesign.Desktop;
using NextDesign.Desktop.CustomUI;
namespace CustomUISample
{
public class CustomUISampleEntryPoint : IExtension
{
/// <summary>
/// エクステンション活性化時の処理
/// </summary>
/// <param name="context"></param>
public void Activate(IContext context)
{
var registry = context.App.CustomUI;
var extensionName = context.ExtensionInfo.Name;
// カスタムエディタの登録
var customEditorDescriptor = new CustomEditorDescriptor(
typeof(CustomEditorViewModel).FullName,
CustomEditorViewModel.DefinitionDescriptor
);
registry.RegisterCustomEditor<CustomEditorViewModel, CustomEditor>(extensionName, customEditorDescriptor);
// カスタムインスペクタの登録
var customInspectorDescriptor = new CustomInspectorDescriptor(
typeof(CustomInspector).FullName,
"カスタムインスペクタ",
(CustomInspectorDescriptor.DisplayOrderNodeShapeDefinition + 1)
);
registry.RegisterCustomInspector<CustomInspectorViewModel, CustomInspector>(extensionName, customInspectorDescriptor);
// カスタムナビゲータの登録
// モデルナビゲータとプロダクトラインの間に表示します
var customNavigatorDescriptor = new CustomNavigatorDescriptor(
typeof(CustomNavigator).FullName,
"カスタムナビゲータ",
(CustomNavigatorDescriptor.DisplayOrderModel + 1),
@"pack://application:,,,/NextDesign;component/Resources/Images/ModelNavigator.png"
);
registry.RegisterCustomNavigator<CustomNavigatorViewModel, CustomNavigator>(extensionName, customNavigatorDescriptor);
}
/// <summary>
/// エクステンション非活性化時の処理
/// </summary>
/// <param name="context"></param>
public void Deactivate(IContext context)
{
var registry = context.App.CustomUI;
var extensionName = context.ExtensionInfo.Name;
// カスタムUIの登録解除
registry.UnRegisterAllCustomUIs(extensionName);
}
}
}
View クラスでの UI の実装
View クラスにコントロールを配置します。
カスタムエディタ
カスタムエディタのビューを定義します。
CustomEditor.xaml
<UserControl x:Class="CustomUISample.View.Editor.CustomEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CustomUISample.View.Editor"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="40"/>
<RowDefinition Height="1"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid VerticalAlignment="Center" Margin="5,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Label Content="ビュー:" />
<ComboBox Height="23" Width="150" Margin="5,0" >
<ComboBoxItem Name="m_FormItem" Content="フォーム" IsSelected="True"/>
<ComboBoxItem Name="m_GridItem" Content="グリッド" />
</ComboBox>
</StackPanel>
</Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" Margin="10,0">
<TextBlock Text="名前:" />
<TextBlock Text="{Binding Path=Name}" Margin="5,0" />
</StackPanel>
<Border Grid.Row="2" BorderThickness="0,1,0,0" BorderBrush="LightGray" HorizontalAlignment="Stretch" />
<!--フォーム風ビュー-->
<Grid Grid.Row="3" Visibility="{Binding ElementName=m_FormItem, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" Margin="10,20,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="説明:" VerticalAlignment="Top" Margin="0,2,0,0" />
<TextBox Grid.Column="1" Text="{Binding Path=Description}" MinHeight="150" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Row="1" Text="クラス名:" VerticalAlignment="Center" />
<TextBlock Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Text="{Binding Path=ClassName}" Margin="5,0" HorizontalAlignment="Left"/>
</Grid>
<!--グリッドビュー-->
<DataGrid Grid.Row="3" ItemsSource="{Binding Path=Children}"
Visibility="{Binding ElementName=m_GridItem, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"
AutoGenerateColumns="True" Margin="10,20,10,0"
HorizontalScrollBarVisibility="Auto"/>
</Grid>
</UserControl>
カスタムインスペクタ
カスタムインスペクタのビューを定義します。
CustomInspector.xaml
<UserControl x:Class="CustomUISample.View.Inspector.CustomInspector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CustomUISample.View.Inspector"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBlock Text="{Binding Path=Name}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</UserControl>
カスタムナビゲータ
カスタムナビゲータのビューを定義します。
CustomNavigator.xaml
<UserControl x:Class="CustomUISample.View.Navigator.CustomNavigator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CustomUISample.View.Navigator"
xmlns:viewModel="clr-namespace:CustomUISample.ViewModel.Navigator"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="OverridesDefaultStyle" Value="False"/>
</Style>
<HierarchicalDataTemplate DataType="{x:Type viewModel:CustomNavigatorItemViewModel}" ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Icon}" Height="16" Width="16"/>
<TextBlock Text="{Binding Path=Model.Name}" Margin="5,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
</HierarchicalDataTemplate>
</UserControl.Resources>
<Grid>
<TreeView x:Name="m_Tree" ItemsSource="{Binding Path=Items}" SelectedItemChanged="TreeView_SelectedItemChanged"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</Grid>
</UserControl>
カスタムナビゲータのビューの振る舞いを実装します。
CustomNavigator.xaml.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CustomUISample.ViewModel.Navigator;
namespace CustomUISample.View.Navigator
{
/// <summary>
/// CustomNavigator.xaml の相互作用ロジック
/// </summary>
public partial class CustomNavigator : UserControl
{
public CustomNavigator()
{
InitializeComponent();
}
/// <summary>
/// ツリーの選択変更
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var vm = DataContext as CustomNavigatorViewModel;
var itemVM = m_Tree.SelectedItem as CustomNavigatorItemViewModel;
if (itemVM != null)
{
vm.SelectedItem = itemVM.Model;
}
}
}
}
カスタムエディタのビュー追加
対象モデルのビューにカスタムエディタを追加します。
操作手順
- モデルナビゲータでカスタムエディタを表示する対象モデルを選択します。
- コンテキストメニューの [ビューの追加] を選択します。
- ビューの追加候補の中に組み込んだカスタムエディタが [カスタムエディタ] の名称で表示されるので選択し、ビューを追加します。
- メインエディタで追加したビューに切り替えると、組み込んだカスタムエディタで対象モデルを表示・編集できます。