OpenXingsCore 1.1.0
dotnet add package OpenXingsCore --version 1.1.0
NuGet\Install-Package OpenXingsCore -Version 1.1.0
<PackageReference Include="OpenXingsCore" Version="1.1.0" />
<PackageVersion Include="OpenXingsCore" Version="1.1.0" />
<PackageReference Include="OpenXingsCore" />
paket add OpenXingsCore --version 1.1.0
#r "nuget: OpenXingsCore, 1.1.0"
#:package OpenXingsCore@1.1.0
#addin nuget:?package=OpenXingsCore&version=1.1.0
#tool nuget:?package=OpenXingsCore&version=1.1.0
OpenXingsCore
A WPF-based .NET framework for industrial monitoring and control applications.
OpenXingsCore provides a structured architecture for building scalable desktop applications with hierarchical data models, event-driven communication, command execution, and a rich set of dashboard UI components.
Table of Contents
- Overview
- Requirements
- Architecture
- Project Structure
- Core Components
- Getting Started
- Usage Examples
- Dependencies
- License
Overview
OpenXingsCore is designed for industrial automation, manufacturing monitoring, and control systems. It offers:
- Path-based data model registration via
ModelHubandModelRegistry - Global event bus for reactive data propagation across the application
- Global command bus (CQRS-style) for action requests and execution
- Task-based logic with declarative
TaskBuilderfor state-driven behavior - Handler system for managing execution contexts and task queues
- Dashboard UI with zoomable canvas, chart controls, and extensible templates
The OpenXingsAppTest project is a sample application demonstrating framework usage, including custom ModelHubs, ViewModels, and Command executors.
Requirements
| Requirement | Version |
|---|---|
| .NET | 9.0 |
| Target OS | Windows 10.0.26100.0 or later |
| UI | WPF |
Architecture
High-Level Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Application Layer │
│ (OpenXingsAppTest: MyAppComposer, ViewModels, Views) │
└───────────────────────────┬─────────────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────────┐
│ OpenXingsCore │
├──────────────┬──────────────┬──────────────┬────────────────────┤
│ Models │ Commands │ Handlers │ ViewModels/Views │
│ ModelHub │ GlobalCmdBus│ HandlerDefault│ Dashboard │
│ ModelValue │ │ TaskDefault │ Controls │
│ ModelRegistry│ │ TaskBuilder │ Templates │
│ GlobalEventBus│ │ │ │
└──────────────┴──────────────┴──────────────┴────────────────────┘
Data Flow
- Model Registration:
ModelHubregistersModelValue<T>instances withModelRegistryandGlobalEventBus. - Value Changes: When
ModelValue.Valuechanges,GlobalEventBuspublishesEventArgsModelValueChanged. - Subscribers: ViewModels, Handlers, and other components subscribe to model addresses and react to changes.
- Commands:
GlobalCommandBusroutesActionRequestobjects to registeredIExecutorimplementations. - Tasks:
HandlerDefaultevaluatesTaskDefaultconditions and executes expressions that read/write model values.
Project Structure
OpenXingsCore/
├── OpenXingsCore/ # Core framework library
│ ├── Models/ # ModelHub, ModelValue, ModelRegistry, GlobalEventBus
│ ├── Commands/ # GlobalCommandBus
│ ├── Handlers/ # HandlerDefault, TaskBuilder, TaskDefault
│ ├── ViewModels/ # Dashboard ViewModels and Controls
│ └── Views/ # WPF controls, pages, templates
│
├── OpenXingsCore/ # Core framework library
│ ├── Args/ # EventArgs, ModelKey, RefArgsModelValue
│ ├── Commands/ # GlobalCommandBus, CommandResult, ActionCommand
│ ├── Constants.cs # Message priorities, config paths
│ ├── Converters/ # Value converters for WPF
│ ├── Datas/ # HandlerContext, SettingDefault
│ ├── Handlers/ # HandlerDefault, HandlerHub
│ ├── Models/ # Data model layer
│ │ ├── ModelHub.cs # Container for ModelValue registration
│ │ ├── ModelValue.cs # Typed observable value holder
│ │ ├── ModelRegistry.cs # Global model lookup by PathKey + model name
│ │ ├── ModelAddress.cs # Path:ModelName address
│ │ ├── GlobalEventBus.cs # Pub/sub for model value changes
│ │ ├── PathKey.cs # Hierarchical path identifier
│ │ └── Logistics/ # LogiModelPort, LogiModelStage, LogiModelLane
│ ├── Tasks/ # Task execution
│ │ ├── TaskBuilder.cs # Fluent API for TaskDefault
│ │ ├── TaskDefault.cs # State, condition, action, timeout
│ │ ├── ExpressionBuilder.cs # Model key binding for expressions
│ │ └── SeriesTaskDefault.cs # Sequential task execution
│ ├── States/ # State definitions
│ ├── Utils/ # ExpressionEvaluator, ModelResolver
│ ├── UtilityInterface/ # IExecutor, IModelValue, ISubscribe, etc.
│ ├── ViewModels/ # MVVM ViewModels
│ │ ├── Controls/ # ViewModelButton, ViewModelInfo, ViewModelChart*, etc.
│ │ ├── Logistics/ # ViewModelPort, ViewModelStage, ViewModelLane
│ │ ├── Pages/ # ViewModelDashboard, ViewModelSystemMonitor
│ │ ├── Handlers/ # ViewModelHandler
│ │ └── Dashboard/ # DashboardColumnBuilder, DashboardItemFactory
│ ├── Views/ # WPF controls and pages
│ │ ├── Controls/ # ControlButton, ControlChart*, ControlPort, etc.
│ │ ├── Pages/ # PageDashboard, PageSystemMonitor, PageSettings
│ │ └── Templates/ # ControlTemplates.xaml, DialogTemplates.xaml
│ ├── Styles/ # BaseStyles, Generic.xaml
│ └── Themes/ # DarkPropertyGridStyle
│
├── OpenXingsCore.Tests/ # Unit tests (xUnit)
│ ├── PathKeyTests.cs
│ ├── ModelRegistryTests.cs
│ ├── TaskBuilderTests.cs
│ └── GlobalCommandBusTests.cs
│
└── OpenXingsAppTest/ # Sample application
├── App.xaml, App.xaml.cs # DI, logging, resource dictionaries
├── MainWindow.xaml # FluentWindow with NavigationView
├── MyAppComposer.cs # AppComposer implementation (HandlerContexts, Executors)
├── MyConstant.cs # App-specific constants
├── Assets/ # Icons, images
├── Commands/ # TestActionRequest
├── HandlerContexts/ # HandlerContextMotor (TaskBuilder, WaitingTasks)
├── Datas/ # SettingData
├── Executors/ # TestExecutor (IExecutor<TestActionRequest, bool>)
├── ModelHubs/ # MHubPort, MHubCarStatus, MHubMachineInfo, etc.
├── Models/ # ModelFuelGauge, ModelTemperature, etc.
├── Services/ # ApplicationHostService
├── States/ # StateHub
├── ViewModels/
│ ├── Controls/ # ViewModelPort (custom)
│ └── Pages/ # ViewModelDashBoardV2, ViewModelMyWindow
└── Views/
├── Controls/ # ControlPort, ModuleInitialize
├── Pages/ # MyMainPage
└── Templates/ # CustomTemplates.xaml (ViewModelPort → ControlPort)
Core Components
1. ModelHub & ModelRegistry
ModelHub groups related ModelValue instances under a PathKey. Registration publishes models to ModelRegistry and GlobalEventBus.
public class MHubPort : ModelHub
{
public MHubPort(PathKey path) : base(path)
{
var name = new ModelValue<string>(Keys.Name, "Default");
Register(name);
// ModelRegistry and GlobalEventBus are updated automatically
}
}
ModelRegistry provides global lookup by path and model name:
if (ModelRegistry.TryGet<ModelValue<double>>(path, "TEMPERATURE", out var model))
model.Value = 25.0;
2. GlobalEventBus
Publish/subscribe for model value changes. Subscribers receive EventArgsModelValueChanged with ModelValue, OldValue, and NewValue.
GlobalEventBus.Instance.Subscribe(model.Address, (sender, arg) =>
{
Console.WriteLine($"{arg.ModelValue.Name}: {arg.OldValue} → {arg.NewValue}");
});
3. GlobalCommandBus
CQRS-style command dispatch. Register executors, then send commands.
// Register executor
GlobalCommandBus.Instance.Register<TestActionRequest, bool>(new TestExecutor(), "test");
// Send command
var result = GlobalCommandBus.Instance.Send<TestActionRequest, bool>(
new TestActionRequest("Hello"));
Supports IExecutor<TCommand, TResult> and IAsyncExecutor<TCommand, TResult>.
4. TaskBuilder & TaskDefault
Declarative task definition with conditions, actions, timeouts, and priority.
var task = TaskBuilder
.On(StateHub.StopNotReady)
.Priority(ENUM_MSG_PRIORITY.NORMAL)
.When("P1 > 100")
.WithKeys((pathKey, modelKey)) // 또는 .WithModels(modelInfo1, modelInfo2)
.Do("P2 = P1")
.WithKeys((pathKey, key1), (pathKey, key2))
.OnTimeout(3000, "P1 = 0")
.WithKeys((pathKey, modelKey))
.Build();
handlerContext.AddWaitingTask(task);
5. AppComposer
Root composition: HandlerContexts, Handlers, model registration, Executors. Manages start/stop lifecycle and JSON serialization. 조합 순서: 1) 모델 등록, 2) HandlerContext 추가, 3) Executor 등록.
public class MyAppComposer : AppComposer
{
public MyAppComposer(SettingData setting) : base(setting)
{
_modelLayer.RegisterAll();
AddHandlerContext(_modelLayer.GetHandlerContexts()); // HandlerContextMotor 등
RegisterExecutors();
// Handlers are created from HandlerContexts on Start()
}
}
6. HandlerDefault
Executes TaskDefault instances from HandlerContext.WaitingTasks in a loop. Evaluates conditions, runs expressions/commands/delegates, and notifies state changes via HandlerHub.
7. Dashboard & ViewModels
- ViewModelDashboard:
ItemsTop,ItemsBottom,ItemsRight,ItemsCanvas(ObservableCollections ofViewModelCanvasItem). - PageDashboard: Uses
VirtualizingCanvas,FastZoomBorder, and pan/zoom. Items are placed byX/Y. - DataTemplates:
ControlTemplates.xamlmaps ViewModels to controls. Applications can override viaCustomTemplates.xaml.
Built-in ViewModels: ViewModelButton, ViewModelInfo, ViewModelStatus, ViewModelEdit, ViewModelChartAngular, ViewModelChartBar, ViewModelChartTrace, ViewModelColor, ViewModelImage, ViewModelPort, ViewModelStage, ViewModelLane, ViewModelHandler, ViewModelArrow, ViewModelHubGroupBorder, ViewModelGroupStack, ViewModelGroupGrid.
Getting Started
Build
dotnet build OpenXingsCore.sln
Run Sample Application
dotnet run --project OpenXingsAppTest
Create a New Application
- Add a project reference to
OpenXingsCore. - Implement
AppComposer(or inherit from it): register models, AddHandlerContext(HandlerContext list), and register Executors. - Register
PageDashboardandViewModelDashboard(or custom) with your navigation/DI. - Define ModelHubs with
PathKeyandModelValue<T>registration; define HandlerContexts that add tasks (e.g. via TaskRepository) toWaitingTasks. - Optionally add
CustomTemplates.xamlto override or extend DataTemplates for your ViewModels.
Run unit tests
dotnet test OpenXingsCore.Tests
Usage Examples
Custom ModelHub
public class MHubPort : ModelHub
{
public static class Keys
{
public static readonly ModelKey<ModelValue<string>> Name = new("NAME");
public static readonly ModelKey<ModelValue<int>> NumOfPass = new("NUM_OF_PASS");
}
public MHubPort(PathKey path) : base(path)
{
Register(new ModelValue<string>(Keys.Name, "Port_1"));
Register(new ModelValue<int>(Keys.NumOfPass, 0));
}
}
Custom ViewModel and Control
- Create ViewModel extending
ViewModelHubDefaultorViewModelCanvasItem. - Create UserControl (e.g.,
ControlPort.xaml). - In
CustomTemplates.xaml:
<DataTemplate DataType="{x:Type viewmodel:ViewModelPort}">
<local:ControlPort/>
</DataTemplate>
- Merge
CustomTemplates.xamlinApp.xaml:
<ResourceDictionary Source="/YourApp;component/Views/Templates/CustomTemplates.xaml"/>
Sending Commands from UI
vm.HandlerButtonClick += (sender, modelInfo) =>
{
var request = new TestActionRequest("Button 0");
var result = GlobalCommandBus.Instance.Send<TestActionRequest, bool>(request);
};
Dependencies
| Package | Purpose |
|---|---|
| CommunityToolkit.Mvvm | MVVM, ObservableObject, RelayCommand |
| LiveChartsCore.SkiaSharpView.WPF | Charts and gauges |
| Microsoft.Extensions.Hosting | Dependency injection, logging |
| Serilog | Structured logging |
| Newtonsoft.Json | JSON serialization |
| Wpf.Controls.PanAndZoom | Canvas zoom/pan |
| SharpVectors.Wpf | SVG rendering |
| Microsoft.Xaml.Behaviors.Wpf | XAML behaviors |
| Wpf.Ui | Fluent-style UI (referenced via DLL) |
License
This project is licensed under the MIT License.
MIT License
Copyright (c) 2026 OpenXings
See the LICENSE file for the full text.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0-windows10.0.26100 is compatible. net10.0-windows was computed. |
-
net9.0-windows10.0.26100
- CommunityToolkit.Mvvm (>= 8.4.2)
- Extended.Wpf.Toolkit (>= 5.0.0)
- Google.Protobuf (>= 3.29.3)
- Grpc.Net.Client (>= 2.67.0)
- LiveChartsCore.SkiaSharpView.WPF (>= 2.0.0)
- Microsoft.Extensions.Hosting (>= 10.0.5)
- Microsoft.Extensions.Logging (>= 10.0.5)
- Microsoft.Extensions.Logging.Console (>= 10.0.5)
- Microsoft.Xaml.Behaviors.Wpf (>= 1.1.142)
- Newtonsoft.Json (>= 13.0.4)
- Serilog.Extensions.Logging (>= 10.0.0)
- Serilog.Sinks.File (>= 7.0.0)
- SharpGL.WPF (>= 3.1.1)
- SharpVectors.Wpf (>= 1.8.5)
- Wpf.Controls.PanAndZoom (>= 2.3.4)
- WPF-UI (>= 4.2.0)
- WPF-UI.DependencyInjection (>= 4.2.0)
- WPF-UI.Tray (>= 4.2.0)
- YamlDotNet (>= 16.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.