皆さん、こんにちは。私は沙漠の果ての狼です。今日はWPFのオープンソースプロジェクト「NodeNetwork」を紹介します。これを使うと、ネットワークトポロジ図を素早く構築・カスタマイズできます。
一、はじめに
現代のソフトウェア開発では、データの可視化とインタラクティブ性がますます注目されています。これを実現するために、通常は各種のチャート、表、ネットワークトポロジ図などのコントロールを使用します。しかし、特定のシナリオではこれらのコントロールでは要件を満たせない場合があり、その場合はデータを表示・処理するためのカスタム方法が必要になります。NodeNetworkはそのようなカスタム方法の一つであり、C# WPFベースのオープンソースプロジェクトで、ネットワークトポロジ図を素早く構築・カスタマイズできます。
NodeNetworkのコードはGitHubでホストされており、オランダの開発者Wouterdekによって作成・保守されています。この記事では、NodeNetworkの紹介と分析を行い、読者の皆様がNodeNetworkのコアコンセプト、適用シナリオ、使用方法を理解し、NodeNetworkを開発するためのテクニックや経験を身につけられることを目指します。
リポジトリアドレス:https://github.com/Wouterdek/NodeNetwork
リポジトリスクリーンショット:

リポジトリのソースコード構成:

二、サンプル
1. 電卓サンプル
このサンプルでは、ユーザーがノードエディターを使用して数式を作成できます。ノードを変更すると、結果の値が自動的に計算され更新されます。このアプリケーションには、ノード検証、カスタムノードサブクラス、値入力/出力、カスタム入力エディター、ノードリストなどが含まれています。
以下が電卓サンプルアプリケーションのデモです:

2. コードジェネレーターサンプル
このサンプルでは、ユーザーがLUAコードを作成できます。Unreal Engineのブループリントと同様に、エディターには実行フローとデータフローがあります。カスタム入出力ポートとノードエディターにより、より直感的な体験が提供されます。
以下がコードジェネレーターアプリケーションのスクリーンショットです:

3. シェーダーエディターサンプル
このライブラリのより実用的な例としては、シェーダーエディターが挙げられます。
以下は、NodeNetworkを使用して作成されたシェーダーエディターサンプルのデモです:

これらのサンプルアプリケーションはこちらからダウンロードでき、そのソースコードはリポジトリに含まれています。ライブラリのバイナリバージョンはNuGetで入手可能です。
三、特徴
- .NET Framework 4.7.2 および .NET Core 3.1 以降向けに構築されています。
- オープンで寛容なライセンス - Apache-2.0 license。
- 最新のリアクティブMVVMコードで構築された、インタラクティブで信頼性の高いコントロール。
- スムーズなパンとズームのコントロール。
- 自動レイアウトシステム。
- 高度にカスタマイズ可能でありながら、デフォルトで使いやすい。
- 強力なノードと接続の検証サポート。
- 大量の単体テストによるサポート。
- ...
四、NodeNetworkのコアコンセプト
以下の内容は、リポジトリのコンポーネント説明ページを参照してください。
1. ノード
ノードはNodeNetworkにおける最も基本的な要素であり、任意のデータソースまたは処理ユニットを表します。各ノードは1つ以上の入力ポートと出力ポートを含むことができ、それぞれノードが受信および出力するデータを表します。NodeNetworkには、定数ノード、計算ノード、入出力ノードなど、いくつかの一般的なノードタイプが組み込まれており、カスタムノードタイプもサポートしています。

2. 接続
接続はNodeNetworkにおける中心的な概念であり、ノード間のデータ転送関係を表します。各接続にはソースポートとターゲットポートがあり、ソースポートはデータのソースを、ターゲットポートはデータの目的地を示します。接続には、色や線の太さなど、接続に関する追加情報を記述するメタデータを含めることもできます。

3. ポート
ポートはノードの入力または出力エンドポイントであり、他のノードとの接続に使用されます。各ポートにはタイプがあり、そのポートが受信または出力できるデータタイプを示します。ポートには、ラベルや説明など、ポートの機能と役割を説明するための他の属性もあります。
4. GUI
NodeNetworkはWPFフレームワークに基づいて実装されているため、強力なGUIシステムを備えています。NodeNetworkでは、各ノードと接続をグラフィカルな要素として表示でき、ユーザーはドラッグ、ズームなどの操作でこれらの要素を操作できます。
5. レイアウト
レイアウトはNodeNetworkのもう一つの重要な概念であり、ノードと接続の位置とサイズを制御します。NodeNetworkでは、自由レイアウト、グリッドレイアウト、力指向レイアウトなど、さまざまなレイアウト方法が提供されています。ユーザーは特定の要件に応じて異なるレイアウト方法を選択でき、コードやGUIを介してレイアウトのカスタマイズと調整を行うことができます。
6. シリアル化とデシリアル化
実際のアプリケーションでは、ノードと接続をファイルやデータベースに保存したり、ファイルやデータベースから読み取ったりする必要があります。これを実現するために、NodeNetworkはシリアル化とデシリアル化の機能を提供しています。シリアル化はノードと接続をデータストリームに変換するプロセスであり、デシリアル化はデータストリームをノードと接続に変換するプロセスです。NodeNetworkはXML、JSON、バイナリなど、複数の異なるシリアル化形式をサポートしており、ユーザーは特定の要件に応じて異なる形式を選択できます。
五、NodeNetworkの適用シナリオ
NodeNetworkには幅広い適用シナリオがあります。以下にその一部を紹介します。
1. データ処理と分析
NodeNetworkは、データ処理と分析のツールを素早く構築するのに役立ちます。例えば、異なるデータ処理ノードを接続してグラフィカルなワークフローを作成し、データの前処理、変換、分析を実現できます。
2. グラフィカルエディター
NodeNetworkは、グラフィカルエディターを素早く構築するのに役立ちます。例えば、特定のパラメータやオプションを編集・設定するためのグラフィカルインターフェースを作成でき、これらのパラメータやオプションをノードと接続を介して対話・転送できます。
3. 可視化とインタラクティブ表示
NodeNetworkは、可視化とインタラクティブ表示ツールを素早く構築するのに役立ちます。例えば、特定のデバイスやシステムの接続関係と状態を表示するためのグラフィカルなネットワークトポロジ図を作成できます。ユーザーはノードと接続を介して対話・制御(ノードや接続の追加、削除、変更など)を行うことができます。
六、NodeNetworkの使用方法
NodeNetworkの使用方法は非常に簡単で、以下の手順で行います(30行未満のコードによるHello worldを参照)。
まず、Dotnet 8を使用してWPFプロジェクトを作成し、プロジェクト名をNodeNetworkTestとします。 .NET Framework 4.7.2以上または.NET CORE 3.x以上を使用できますが、サイト管理者は.NET 8のプレビュー2がリリースされたばかりで試してみたかったため、使用しています。
1. NodeNetworkのインストール
NodeNetworkはNuGetパッケージマネージャーからインストールできます。Visual Studioで「パッケージマネージャーコンソール」を開き、以下のコマンドを入力してNodeNetworkをインストールします。
Install-Package NodeNetwork
2. NodeNetworkビューの登録
NodeNetworkライブラリ全体でMVVMが一貫して使用されています。MVVMの紹介についてはこちらを参照してください。ライブラリの要素を使用するには、適切なビューを作成し、対応するViewModelインスタンスを提供する必要があります。
ライブラリを使用する前に、App.xaml.csファイルのOnStartupメソッド内でNNViewRegistrar.RegisterSplat()メソッドを使用して、NodeNetworkのビューと対応するViewModelを登録・関連付けます。
using System.Windows;
using NodeNetwork;
namespace NodeNetworkTest;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
NNViewRegistrar.RegisterSplat();
}
}
3. ビューの作成
MainWindow.xamlを開き、NodeNetwork名前空間xmlns:nodenetwork="clr-namespace:NodeNetwork.Views;assembly=NodeNetwork"を追加し、NetworkViewビュー<nodenetwork:NetworkView x:Name="networkView" />を追加します。NetworkViewはネットワークトポロジ図全体を表します。
<Window x:Class="NodeNetworkTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:nodenetwork="clr-namespace:NodeNetwork.Views;assembly=NodeNetwork"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<nodenetwork:NetworkView x:Name="networkView" />
</Grid>
</Window>
4. ノードと接続の作成
NodeNetworkでは、ノードと接続の作成は非常に簡単です。まず、NetworkViewModelを作成します。これはNetworkViewビューのViewModelです。以下のコードで作成できます。
var network = new NetworkViewModel();
networkView.ViewModel = network;
次に、以下のコードで最初のノードを作成します。
var node1 = new NodeViewModel();
node1.Name = "ノード1";
network.Nodes.Add(node1);
そして、最初のノードに入力ポートを作成します。
var node1Input = new NodeInputViewModel();
node1Input.Name = "ノード1入力";
node1.Inputs.Add(node1Input);
2番目のノードを作成し、同様の方法でこのノードに出力ポートを作成します。
var node2 = new NodeViewModel();
node2.Name = "ノード2";
network.Nodes.Add(node2);
var node2Output = new NodeOutputViewModel();
node2Output.Name = "ノード2出力";
node2.Outputs.Add(node2Output);
最後に、以下のコードでノード1の入力ポートとノード2の出力ポートを接続します。
var connection = new ConnectionViewModel(network, node1Input, node2Output);
network.Connections.Add(connection);
完全なコードは以下の通りです。
using DynamicData;
using NodeNetwork.ViewModels;
using System.Windows;
namespace NodeNetworkTest;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// NetworkViewビューのViewModelインスタンスを作成
var network = new NetworkViewModel();
// ビュー(networkView)にviewmodel(network)を割り当て
networkView.ViewModel = network;
// 最初のノードのViewModelを作成し、名前を設定してnetworkに追加
var node1 = new NodeViewModel();
node1.Name = "ノード1";
network.Nodes.Add(node1);
// 最初のノードの入力ポートViewModelを作成し、名前を設定して最初のノードに追加
var node1Input = new NodeInputViewModel();
node1Input.Name = "ノード1入力";
node1.Inputs.Add(node1Input);
// 2番目のノードのViewModelを作成し、名前を設定してnetworkに追加し、同様の方法で出力を追加
var node2 = new NodeViewModel();
node2.Name = "ノード2";
network.Nodes.Add(node2);
var node2Output = new NodeOutputViewModel();
node2Output.Name = "ノード2出力";
node2.Outputs.Add(node2Output);
// ノード1の入力ポートとノード2の出力ポートを接続
var connection = new ConnectionViewModel(network, node1Input, node2Output);
network.Connections.Add(connection);
}
}
プログラムを実行して効果を確認します。

サンプルコードはすべて提供しました。こちらからクローンすることもできます。
5. レイアウト
NodeNetworkでは、レイアウトは非常に柔軟で自由です。コードやGUIを介してレイアウトを行うことができます。例えば、以下のコードでノードを指定の位置に配置できます。
node.Position = new Point(100, 100);
以下のコードでネットワークトポロジ図全体のレイアウトを調整できます(レイアウトドキュメントを参照)。
ForceDirectedLayouter layouter = new ForceDirectedLayouter();
var config = new Configuration
{
Network = yourNetwork,
};
layouter.Layout(config, 10000);

6. シリアル化とデシリアル化
NodeNetworkでは、シリアル化とデシリアル化は非常に簡単です。以下のコードでノードと接続をXML形式にシリアル化できます。
var serializer = new XmlSerializer(typeof(NodeNetworkViewModel));
var writer = new StringWriter();
serializer.Serialize(writer, nodeNetwork);
その後、XML文字列をファイルやデータベースに保存できます。デシリアル化も非常に簡単です。以下のコードでXML文字列からノードと接続をデシリアル化できます。
var serializer = new XmlSerializer(typeof(NodeNetworkViewModel));
var reader = new StringReader(xmlString);
var nodeNetwork = (NodeNetworkViewModel)serializer.Deserialize(reader);
七、まとめ
NodeNetworkは非常に実用的で柔軟なC# WPFオープンソースプロジェクトであり、グラフィカルなネットワークトポロジ図を素早く構築し、ノードと接続の対話と転送を実現するのに役立ちます。NodeNetworkは、ノードと接続のカスタマイズ、レイアウトと調整、シリアル化とデシリアル化など、豊富な機能と特徴を提供し、さまざまなアプリケーション要件を満たすことができます。NodeNetworkの適用シナリオは非常に広く、データ処理と分析、グラフィカルエディター、可視化とインタラクティブ表示などがあります。NodeNetworkの使用方法は非常に簡単で、NodeNetworkをインストールし、ノードと接続を作成し、レイアウトと調整を行い、シリアル化とデシリアル化を行うだけです。
- 入門ガイド
このライブラリの簡単なクイックスタートガイドについては、このページのチュートリアルセクションを参照してください。このドキュメントには、セットアップ情報、チュートリアルセクション、サンプル、APIリファレンスが含まれています。
- ライセンス
このライブラリはApache License 2.0の下でライセンスされています。(概要についてはchoosealicense.com/licenses/apache-2.0を参照してください)このライセンスのコピーは、LICENSEとしてリポジトリに含まれています。
- ドキュメント
ドキュメントはこちらで入手できます。ドキュメントに変更を加える場合は、gh-pagesブランチにプルリクエストを送信することで実現できます。
- 貢献
GitHubページでは、バグ報告、パッチ、機能リクエスト、プルリクエストなどを歓迎します。
- WeChat技術交流グループ:WeChat(codewf)を追加して「入群」と送信
- QQ技術交流グループ:771992300。