99 lines
6.7 KiB
Markdown
99 lines
6.7 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- Common/DTS.CommonCore/BusyIndicatorManager/xBusyIndicator.xaml.cs
|
||
|
|
- Common/DTS.CommonCore/BusyIndicatorManager/BusyIndicatorManager.cs
|
||
|
|
generated_at: "2026-04-16T02:11:43.845066+00:00"
|
||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "85046dce961f12c2"
|
||
|
|
---
|
||
|
|
|
||
|
|
# BusyIndicatorManager
|
||
|
|
|
||
|
|
## Documentation: BusyIndicatorManager Module
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 1. Purpose
|
||
|
|
|
||
|
|
This module provides a centralized, singleton-based busy indicator management system for WPF applications, enabling multiple components or operations to request and release busy state independently while ensuring the UI reflects a consistent busy status. It decouples the *initiation* of busy operations (via unique IDs) from the *actual display* of the busy indicator, which is expected to be bound to the `IsBusy` and `Message` properties of the `BusyIndicatorManager` instance. The `xBusyIndicator` class serves as the XAML-backed UI control that presumably consumes this manager (though its current implementation is minimal).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. Public Interface
|
||
|
|
|
||
|
|
#### `BusyIndicatorManager` (Singleton)
|
||
|
|
|
||
|
|
- **`public static BusyIndicatorManager Instance { get; }`**
|
||
|
|
Thread-safe singleton accessor. Returns the single shared instance of `BusyIndicatorManager`. Uses double-checked locking via `SyncRoot`.
|
||
|
|
|
||
|
|
- **`public bool IsBusy { get; }`**
|
||
|
|
Read-only property indicating whether *any* busy request is currently active. Raises `PropertyChanged` on change (via `NotificationObject` base).
|
||
|
|
|
||
|
|
- **`public string Message { get; }`**
|
||
|
|
Read-only property containing the *current* busy message. Reflects the message of the *last added or active* busy request (see `ShowBusy`/`CloseBusy` behavior). Raises `PropertyChanged` on change.
|
||
|
|
|
||
|
|
- **`public void ShowBusy(int id, string busyMessage)`**
|
||
|
|
Registers a new busy request with the given `id`. If `id` is new, it adds the `busyMessage` to the internal dictionary and sets `IsBusy = true` and `Message = busyMessage`. If `id` already exists, it updates the stored message for that `id`, and ensures `IsBusy = true` and `Message = busyMessage` (i.e., overwrites current message regardless of prior state).
|
||
|
|
*Note:* Does *not* deduplicate or prevent multiple `ShowBusy` calls with the same `id`—only updates the message.
|
||
|
|
|
||
|
|
- **`public void CloseBusy(int id)`**
|
||
|
|
Removes the busy request identified by `id`. If no requests remain (`busyParameters.Count == 0`), sets `IsBusy = false` and `Message = ""`. Otherwise, sets `IsBusy = true` and `Message = busyParameters.Last().Value` (i.e., the message of the *last-enumerated* remaining request).
|
||
|
|
*Note:* Enumeration order of `Dictionary<int, string>` is insertion order in .NET, but relying on `Last()` for priority is fragile and not guaranteed to be intuitive.
|
||
|
|
|
||
|
|
#### `xBusyIndicator` (UI Control)
|
||
|
|
|
||
|
|
- **`public xBusyIndicator()`**
|
||
|
|
Constructor. Calls `InitializeComponent()` to load the XAML-defined UI.
|
||
|
|
|
||
|
|
- **`public void Connect(int connectionId, object target)`**
|
||
|
|
Currently **empty implementation**. Presumably intended to associate a UI element (`target`) with a logical connection ID (`connectionId`), but no behavior is defined in the source.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. Invariants
|
||
|
|
|
||
|
|
- **Singleton uniqueness**: Exactly one instance of `BusyIndicatorManager` exists per AppDomain (enforced via `lock` and null-check).
|
||
|
|
- **`IsBusy` truthfulness**:
|
||
|
|
- `IsBusy == true` **iff** `busyParameters.Count > 0`.
|
||
|
|
- `IsBusy == false` **iff** `busyParameters.Count == 0`.
|
||
|
|
- **`Message` consistency**:
|
||
|
|
- When `IsBusy == true`, `Message` equals the `busyMessage` string associated with the *last-enumerated* entry in `busyParameters`.
|
||
|
|
- When `IsBusy == false`, `Message == string.Empty`.
|
||
|
|
- **ID uniqueness per request**: Each `id` in `ShowBusy(id, ...)` maps to one message in `busyParameters`. Reusing an `id` updates the message but does *not* create a new entry.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. Dependencies
|
||
|
|
|
||
|
|
#### Dependencies *of* this module:
|
||
|
|
- **`Microsoft.Practices.Prism.ViewModel.NotificationObject`**: Base class for `BusyIndicatorManager`, enabling property change notifications (`RaisePropertyChanged`).
|
||
|
|
- **`System.Collections.Generic`**: Used for `Dictionary<int, string>`.
|
||
|
|
- **`System.Linq`**: Used for `busyParameters.Last()` in `CloseBusy`.
|
||
|
|
- **WPF UI framework**: `xBusyIndicator` inherits from `System.Windows.Controls.UserControl` (implied by `InitializeComponent()` and XAML usage).
|
||
|
|
|
||
|
|
#### Dependencies *on* this module:
|
||
|
|
- **UI components** (not visible in source): Presumably XAML views bind to `BusyIndicatorManager.Instance.IsBusy` and `.Message` to drive a `BusyIndicator` control (e.g., from `Xceed.Wpf.Toolkit`).
|
||
|
|
- **`xBusyIndicator.xaml`**: The XAML file for `xBusyIndicator` (not provided), which likely consumes `BusyIndicatorManager` to display the busy state.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 5. Gotchas
|
||
|
|
|
||
|
|
- **`CloseBusy` message selection is arbitrary**: `busyParameters.Last()` uses dictionary enumeration order, which is insertion order in .NET, but this is not documented as a contract. If multiple requests are active, the displayed message may change unexpectedly when an unrelated request is closed.
|
||
|
|
*Example:* Requests added in order `id=1`, `id=2`, `id=3` → closing `id=2` changes message to that of `id=3`, even if `id=1` was the "primary" request.
|
||
|
|
|
||
|
|
- **No validation on `id`**: `ShowBusy` and `CloseBusy` accept any `int`. Duplicates are allowed (with update semantics), but no error is thrown for invalid IDs.
|
||
|
|
|
||
|
|
- **`Connect` method is a stub**: `xBusyIndicator.Connect` has no implementation. Its purpose is unclear—without knowing the intended use of `connectionId` and `target`, this API is non-functional.
|
||
|
|
|
||
|
|
- **No thread-safety for `busyParameters`**: While singleton instantiation is thread-safe, all operations on `busyParameters` (e.g., `ContainsKey`, `Add`, `Remove`, `Last`) are *not* synchronized. Concurrent calls to `ShowBusy`/`CloseBusy` from multiple threads may cause race conditions (e.g., `KeyNotFoundException`, corrupted dictionary state).
|
||
|
|
*Note:* The singleton uses a lock for initialization only.
|
||
|
|
|
||
|
|
- **Message overwriting on `id` reuse**: Calling `ShowBusy(42, "A")` then `ShowBusy(42, "B")` updates the message but does *not* reset `IsBusy` if it was already `true`. This may be intentional, but could mask bugs if callers assume each `ShowBusy` is independent.
|
||
|
|
|
||
|
|
- **Hardcoded property names**: `RaisePropertyChanged("IsBusy")` uses string literals. No compile-time safety—renaming properties would break binding silently.
|
||
|
|
|
||
|
|
- **No timeout or cancellation support**: Busy state persists indefinitely until `CloseBusy(id)` is called. No mechanism to auto-release or cancel long-running requests.
|
||
|
|
|
||
|
|
- **`Xceed.Wpf.Toolkit` imported but unused**: The namespace is imported in `xBusyIndicator.xaml.cs`, but no `Xceed.Wpf.Toolkit` types are referenced in the provided code. May indicate future use or leftover artifact.
|