29 KiB
UI Framework
**Referenced Files in This Document** - [Program.cs](file://ClassicAssist.Avalonia/Program.cs) - [App.axaml](file://ClassicAssist.Avalonia/App.axaml) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [MainWindow.axaml](file://ClassicAssist.Avalonia/Views/MainWindow.axaml) - [MainWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/MainWindow.axaml.cs) - [DialogWindow.axaml](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml) - [DialogWindow.axaml.cs](file://ClassicAssist.Avalonia/Views/DialogWindow.axaml.cs) - [DialogWindowViewModel.cs](file://ClassicAssist.Avalonia/ViewModels/DialogWindowViewModel.cs) - [HexDumpControl.axaml](file://ClassicAssist.Avalonia/Controls/HexDumpControl.axaml) - [HexDumpControl.axaml.cs](file://ClassicAssist.Avalonia/Controls/HexDumpControl.axaml.cs) - [EditTextBlock.axaml](file://ClassicAssist.Avalonia/Controls/EditTextBlock.axaml) - [EditTextBlock.axaml.cs](file://ClassicAssist.Avalonia/Controls/EditTextBlock.axaml.cs) - [TextBoxKey.axaml](file://ClassicAssist.Avalonia/Controls/TextBoxKey.axaml) - [TextBoxKey.axaml.cs](file://ClassicAssist.Avalonia/Controls/TextBoxKey.axaml.cs) - [GroupBox.Theme.xaml](file://ClassicAssist.Avalonia/Controls/GroupBox.Theme.xaml) - [GroupBox.cs](file://ClassicAssist.Avalonia/Controls/GroupBox.cs) - [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs) - [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs) - [AvalonEditBehaviour.cs](file://ClassicAssist.Avalonia/Misc/AvalonEditBehaviour.cs) - [CloseOnClickBehaviour.cs](file://ClassicAssist.Avalonia/Misc/CloseOnClickBehaviour.cs) - [ComboBoxBehavior.cs](file://ClassicAssist.Avalonia/Misc/ComboBoxBehavior.cs) - [DateTimeToTimeSpanValueConverter.cs](file://ClassicAssist.Avalonia/Misc/DateTimeToTimeSpanValueConverter.cs) - [InverseBooleanValueConverter.cs](file://ClassicAssist.Avalonia/Misc/InverseBooleanValueConverter.cs) - [JoinArrayValueConverter.cs](file://ClassicAssist.Avalonia/Misc/JoinArrayValueConverter.cs) - [ListBoxAutoScrollBehaviour.cs](file://ClassicAssist.Avalonia/Misc/ListBoxAutoScrollBehaviour.cs) - [LockStatusValueConverter.cs](file://ClassicAssist.Avalonia/Misc/LockStatusValueConverter.cs) - [PacketEntryBinaryValueConverter.cs](file://ClassicAssist.Avalonia/Misc/PacketEntryBinaryValueConverter.cs) - [PacketEntryTextValueConverter.cs](file://ClassicAssist.Avalonia/Misc/PacketEntryTextValueConverter.cs) - [StringToResourceConverter.cs](file://ClassicAssist.Avalonia/Misc/StringToResourceConverter.cs) - [WindowInitializedBehaviour.cs](file://ClassicAssist.Avalonia/Misc/WindowInitializedBehaviour.cs) - [WindowResizeBehaviour.cs](file://ClassicAssist.Avalonia/Misc/WindowResizeBehaviour.cs) - [HueEntryToRectanglesValueConverter.cs](file://ClassicAssist.Avalonia/Misc/HueEntryToRectanglesValueConverter.cs) - [BaseViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/BaseViewModel.cs) - [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs) - [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs) - [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)Table of Contents
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
Introduction
This document describes the UI framework implementation for ClassicAssist.Avalonia, focusing on the MVVM architecture with Avalonia UI, cross-platform abstractions, theme and styling, custom controls, binding system, behaviors, performance strategies, and window management. It provides a clear separation between Views, ViewModels, and Models, and explains how platform-specific implementations are abstracted to support multiple targets consistently.
Project Structure
The UI layer is organized into distinct folders that reflect MVVM responsibilities:
- Controls: Reusable UI components (e.g., HexDumpControl, EditTextBlock, TextBoxKey).
- Views: Window and page-level XAML views bound to ViewModels.
- ViewModels: Presentation logic and state exposed to Views.
- Misc: Behaviors, value converters, and cross-cutting utilities.
- App entry points: Application lifecycle and resource initialization.
graph TB
subgraph "Avalonia UI"
Program["Program.cs"]
App["App.axaml / App.axaml.cs"]
MainWindow["Views/MainWindow.axaml(.cs)"]
DialogWindow["Views/DialogWindow.axaml(.cs)"]
end
subgraph "Shared UI Contracts"
IDisp["IDispatcher.cs"]
IInv["IUIInvoker.cs"]
BaseVM["Shared/UI/ViewModels/BaseViewModel.cs"]
MainVM["Shared/UI/ViewModels/MainWindowViewModel.cs"]
end
subgraph "Custom Controls"
Hex["Controls/HexDumpControl.axaml(.cs)"]
EditTxt["Controls/EditTextBlock.axaml(.cs)"]
TxtKey["Controls/TextBoxKey.axaml(.cs)"]
GroupBox["Controls/GroupBox.cs + Theme"]
end
subgraph "Behaviors & Converters"
Behav["Misc/*Behaviour.cs"]
Conv["Misc/*ValueConverter.cs"]
end
Program --> App
App --> MainWindow
MainWindow --> MainVM
DialogWindow --> MainVM
MainWindow --> Hex
MainWindow --> EditTxt
MainWindow --> TxtKey
MainWindow --> GroupBox
MainWindow --> Behav
MainWindow --> Conv
App --> IDisp
App --> IInv
MainVM --> BaseVM
Diagram sources
- Program.cs
- App.axaml
- App.axaml.cs
- MainWindow.axaml
- MainWindow.axaml.cs
- DialogWindow.axaml
- DialogWindow.axaml.cs
- HexDumpControl.axaml
- HexDumpControl.axaml.cs
- EditTextBlock.axaml
- EditTextBlock.axaml.cs
- TextBoxKey.axaml
- TextBoxKey.axaml.cs
- GroupBox.cs
- GroupBox.Theme.xaml
- AvaloniaDispatcher.cs
- AvaloniaUIInvoker.cs
- AvalonEditBehaviour.cs
- CloseOnClickBehaviour.cs
- ComboBoxBehavior.cs
- DateTimeToTimeSpanValueConverter.cs
- InverseBooleanValueConverter.cs
- JoinArrayValueConverter.cs
- ListBoxAutoScrollBehaviour.cs
- LockStatusValueConverter.cs
- PacketEntryBinaryValueConverter.cs
- PacketEntryTextValueConverter.cs
- StringToResourceConverter.cs
- WindowInitializedBehaviour.cs
- WindowResizeBehaviour.cs
- HueEntryToRectanglesValueConverter.cs
- BaseViewModel.cs
- MainWindowViewModel.cs
- IDispatcher.cs
- IUIInvoker.cs
Section sources
- Program.cs
- App.axaml
- App.axaml.cs
- MainWindow.axaml
- MainWindow.axaml.cs
- DialogWindow.axaml
- DialogWindow.axaml.cs
- HexDumpControl.axaml
- HexDumpControl.axaml.cs
- EditTextBlock.axaml
- EditTextBlock.axaml.cs
- TextBoxKey.axaml
- TextBoxKey.axaml.cs
- GroupBox.cs
- GroupBox.Theme.xaml
- AvaloniaDispatcher.cs
- AvaloniaUIInvoker.cs
- AvalonEditBehaviour.cs
- CloseOnClickBehaviour.cs
- ComboBoxBehavior.cs
- DateTimeToTimeSpanValueConverter.cs
- InverseBooleanValueConverter.cs
- JoinArrayValueConverter.cs
- ListBoxAutoScrollBehaviour.cs
- LockStatusValueConverter.cs
- PacketEntryBinaryValueConverter.cs
- PacketEntryTextValueConverter.cs
- StringToResourceConverter.cs
- WindowInitializedBehaviour.cs
- WindowResizeBehaviour.cs
- HueEntryToRectanglesValueConverter.cs
- BaseViewModel.cs
- MainWindowViewModel.cs
- IDispatcher.cs
- IUIInvoker.cs
Core Components
- Application bootstrap and DI setup: The application initializes resources, registers services, and creates the main window.
- Cross-platform dispatching and UI invocation: Abstractions for thread marshaling and UI operations ensure consistent behavior across platforms.
- Custom controls: Specialized controls for hex editing, key input, and text editing with rich UX.
- Behaviors and converters: Declarative enhancements to standard controls and data transformations.
- Window management: Centralized dialog handling and modal workflows.
Section sources
- App.axaml.cs
- AvaloniaDispatcher.cs
- AvaloniaUIInvoker.cs
- HexDumpControl.axaml.cs
- EditTextBlock.axaml.cs
- TextBoxKey.axaml.cs
- DialogWindow.axaml.cs
- DialogWindowViewModel.cs
Architecture Overview
The UI follows MVVM with Avalonia:
- Views declare layout and bind to ViewModels.
- ViewModels expose state and commands, implementing change notifications.
- Models encapsulate domain data and business rules.
- Cross-platform abstractions isolate platform-specific concerns behind shared interfaces.
classDiagram
class IDispatcher {
+Invoke(action)
+BeginInvoke(action)
}
class IUIInvoker {
+ShowDialog(window, viewModel)
+ShowWindow(window, viewModel)
}
class AvaloniaDispatcher
class AvaloniaUIInvoker
class BaseViewModel {
+NotifyPropertyChanged()
}
class MainWindowViewModel
class MainWindow
class DialogWindow
class DialogWindowViewModel
AvaloniaDispatcher ..|> IDispatcher
AvaloniaUIInvoker ..|> IUIInvoker
MainWindowViewModel --|> BaseViewModel
MainWindow --> MainWindowViewModel : "DataContext"
DialogWindow --> DialogWindowViewModel : "DataContext"
MainWindow --> AvaloniaUIInvoker : "uses"
MainWindow --> AvaloniaDispatcher : "uses"
Diagram sources
- IDispatcher.cs
- IUIInvoker.cs
- AvaloniaDispatcher.cs
- AvaloniaUIInvoker.cs
- BaseViewModel.cs
- MainWindowViewModel.cs
- MainWindow.axaml.cs
- DialogWindow.axaml.cs
- DialogWindowViewModel.cs
Detailed Component Analysis
MVVM Implementation
- BaseViewModel provides common change notification and property helpers.
- MainWindowViewModel orchestrates UI state and delegates to services via abstractions.
- Views bind to properties and commands; they remain thin and declarative.
sequenceDiagram
participant User as "User"
participant View as "MainWindow"
participant VM as "MainWindowViewModel"
participant Invoker as "AvaloniaUIInvoker"
participant Dialog as "DialogWindow"
User->>View : Click action
View->>VM : Execute command
VM->>Invoker : ShowDialog(dialogVM)
Invoker->>Dialog : Create and show modal
Dialog-->>VM : Result callback
VM-->>View : Update UI state
Diagram sources
- MainWindow.axaml.cs
- MainWindowViewModel.cs
- AvaloniaUIInvoker.cs
- DialogWindow.axaml.cs
- DialogWindowViewModel.cs
Section sources
- BaseViewModel.cs
- MainWindowViewModel.cs
- MainWindow.axaml.cs
- DialogWindow.axaml.cs
- DialogWindowViewModel.cs
Cross-Platform UI Abstraction Layer
- IDispatcher and IUIInvoker define contracts for UI threading and window/dialog operations.
- AvaloniaDispatcher implements dispatcher semantics for Avalonia’s UI thread.
- AvaloniaUIInvoker implements cross-platform dialog/window presentation using Avalonia primitives.
flowchart TD
Start(["UI Operation"]) --> CheckThread["Check current thread"]
CheckThread --> IsUIThread{"Is UI thread?"}
IsUIThread --> |Yes| Execute["Execute directly"]
IsUIThread --> |No| Marshal["Marshal to UI thread"]
Marshal --> Execute
Execute --> End(["Done"])
Diagram sources
Section sources
Theme System, Styling, and Resources
- Global styles and themes are defined in XAML resources and merged at app startup.
- Control-specific themes (e.g., GroupBox) provide default look-and-feel.
- Resource dictionaries centralize colors, icons, and reusable styles.
graph LR
AppRes["App.axaml resources"] --> Merged["Merged Dictionaries"]
Merged --> Themes["Themes (Dark/Light)"]
Merged --> Styles["Global Styles"]
Merged --> Icons["Icons & Assets"]
Themes --> Controls["Controls (e.g., GroupBox)"]
Styles --> Controls
Icons --> Controls
Diagram sources
Section sources
Custom Controls Library
- HexDumpControl: A specialized control for binary/hex inspection with efficient rendering patterns suitable for large datasets.
- EditTextBlock: An editable text block combining read-only display with inline editing capabilities.
- TextBoxKey: A key-binding capture control for hotkey configuration.
- GroupBox: A themed container control with consistent styling.
classDiagram
class HexDumpControl {
+Data
+Refresh()
}
class EditTextBlock {
+Text
+EditMode(bool)
}
class TextBoxKey {
+KeyBinding
+CaptureKey()
}
class GroupBox {
+Header
}
HexDumpControl <.. EditTextBlock : "used by"
HexDumpControl <.. TextBoxKey : "used by"
GroupBox <.. HexDumpControl : "wraps"
Diagram sources
Section sources
- HexDumpControl.axaml
- HexDumpControl.axaml.cs
- EditTextBlock.axaml
- EditTextBlock.axaml.cs
- TextBoxKey.axaml
- TextBoxKey.axaml.cs
- GroupBox.cs
- GroupBox.Theme.xaml
Binding System, Value Converters, and Behaviors
- ValueConverters transform data for display (e.g., DateTime to TimeSpan, lock status, packet entries, string-to-resource lookup).
- Behaviors add interactivity without code-behind (e.g., auto-scroll, close-on-click, combo box behavior, window resize/initialized hooks).
- Bindings connect View properties to ViewModel commands and properties.
flowchart TD
Data["ViewModel Property"] --> Converter["ValueConverter"]
Converter --> ViewProp["View Property"]
Behavior["Behavior"] --> View["View Element"]
Behavior --> Event["Event/Action"]
Event --> Command["Command in ViewModel"]
Diagram sources
- DateTimeToTimeSpanValueConverter.cs
- InverseBooleanValueConverter.cs
- JoinArrayValueConverter.cs
- LockStatusValueConverter.cs
- PacketEntryBinaryValueConverter.cs
- PacketEntryTextValueConverter.cs
- StringToResourceConverter.cs
- HueEntryToRectanglesValueConverter.cs
- AvalonEditBehaviour.cs
- CloseOnClickBehaviour.cs
- ComboBoxBehavior.cs
- ListBoxAutoScrollBehaviour.cs
- WindowInitializedBehaviour.cs
- WindowResizeBehaviour.cs
Section sources
- DateTimeToTimeSpanValueConverter.cs
- InverseBooleanValueConverter.cs
- JoinArrayValueConverter.cs
- LockStatusValueConverter.cs
- PacketEntryBinaryValueConverter.cs
- PacketEntryTextValueConverter.cs
- StringToResourceConverter.cs
- HueEntryToRectanglesValueConverter.cs
- AvalonEditBehaviour.cs
- CloseOnClickBehaviour.cs
- ComboBoxBehavior.cs
- ListBoxAutoScrollBehaviour.cs
- WindowInitializedBehaviour.cs
- WindowResizeBehaviour.cs
Window Management and Modal Dialogs
- DialogWindow provides a standardized modal dialog shell.
- DialogWindowViewModel coordinates dialog content and results.
- AvaloniaUIInvoker handles creation and lifetime of dialogs/windows uniformly across platforms.
sequenceDiagram
participant Caller as "Caller ViewModel"
participant Invoker as "AvaloniaUIInvoker"
participant Win as "DialogWindow"
participant VM as "DialogWindowViewModel"
Caller->>Invoker : ShowDialog(VM)
Invoker->>Win : Instantiate and set DataContext
Win->>VM : Initialize and render
VM-->>Caller : Return result on close
Diagram sources
Section sources
Dependency Analysis
- Views depend on ViewModels through DataContext bindings.
- ViewModels depend on shared base classes and abstractions (dispatcher, invoker).
- Custom controls encapsulate complex UI logic and can be reused across views.
- Behaviors and converters are loosely coupled and applied declaratively.
graph TB
Views["Views"] --> VMs["ViewModels"]
VMs --> SharedVM["BaseViewModel"]
VMs --> Abstractions["IDispatcher / IUIInvoker"]
Views --> Controls["Custom Controls"]
Views --> Misc["Behaviors & Converters"]
Controls --> Theming["Theme Resources"]
Diagram sources
- MainWindow.axaml.cs
- MainWindowViewModel.cs
- BaseViewModel.cs
- IDispatcher.cs
- IUIInvoker.cs
- HexDumpControl.axaml.cs
- GroupBox.Theme.xaml
Section sources
- MainWindow.axaml.cs
- MainWindowViewModel.cs
- BaseViewModel.cs
- IDispatcher.cs
- IUIInvoker.cs
- HexDumpControl.axaml.cs
- GroupBox.Theme.xaml
Performance Considerations
- Virtualization: Prefer virtualizing panels for large lists to reduce memory and improve scroll performance.
- Incremental updates: Batch collection changes and avoid excessive property notifications during bulk operations.
- Efficient rendering: Use custom controls like HexDumpControl optimized for large binary data; avoid heavy per-item visuals.
- Debounced input: For text inputs and key capture, debounce or throttle events to prevent UI thrashing.
- Resource caching: Cache computed values and converter outputs where appropriate to minimize recomputation.
- Responsive design: Use flexible layouts and responsive sizing to adapt to different screen sizes and DPI settings.
[No sources needed since this section provides general guidance]
Troubleshooting Guide
- Threading issues: Ensure UI updates occur on the UI thread using the dispatcher abstraction.
- Dialog not closing: Verify that dialog results are properly returned and handled by the caller ViewModel.
- Style conflicts: Check resource dictionary merge order and control theme overrides.
- Converter errors: Validate input types and handle nulls gracefully in converters.
- Memory growth: Monitor large collections and enable virtualization; dispose of unused resources.
Section sources
- AvaloniaDispatcher.cs
- AvaloniaUIInvoker.cs
- DialogWindow.axaml.cs
- DialogWindowViewModel.cs
- GroupBox.Theme.xaml
- DateTimeToTimeSpanValueConverter.cs
- InverseBooleanValueConverter.cs
- JoinArrayValueConverter.cs
- LockStatusValueConverter.cs
- PacketEntryBinaryValueConverter.cs
- PacketEntryTextValueConverter.cs
- StringToResourceConverter.cs
- HueEntryToRectanglesValueConverter.cs
Conclusion
ClassicAssist.Avalonia implements a clean MVVM architecture with Avalonia UI, providing robust cross-platform abstractions, a comprehensive theming system, reusable custom controls, and a rich set of behaviors and converters. The design emphasizes separation of concerns, testability, and performance, making it suitable for complex desktop applications requiring responsive and maintainable UI layers.