Files
DP44/enriched-partialglm/DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Classes.md

104 lines
5.8 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.GraphList/Classes/VirtualToggleButton.cs
generated_at: "2026-04-16T11:10:12.391241+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "001b39a3411ec3ba"
---
# Documentation: VirtualToggleButton.cs
## 1. Purpose
`VirtualToggleButton` is a static utility class that provides attached dependency properties to imbue any WPF element with toggle button behavior without requiring inheritance from `ToggleButton`. It enables elements to respond to mouse clicks and keyboard input (Space/Enter) to toggle between checked/unchecked/indeterminate states, and raises the corresponding routed events. This is useful for templated controls or custom elements that need toggle semantics without the overhead of full `ToggleButton` derivation.
---
## 2. Public Interface
### Attached Properties
| Property | Type | Default | Metadata Flags |
|----------|------|---------|----------------|
| `IsLockedProperty` | `Nullable<bool>` | `false` | `BindsTwoWayByDefault`, `Journal` |
| `IsThreeStateProperty` | `bool` | `false` | None |
| `IsVirtualToggleButtonProperty` | `bool` | `false` | None |
### Public Methods
#### `GetIsLocked(DependencyObject d) -> Nullable<bool>`
Retrieves the current locked/checked state of the target element.
#### `SetIsLocked(DependencyObject d, Nullable<bool> value)`
Sets the locked/checked state. Setting to `true` raises `ToggleButton.CheckedEvent`; `false` raises `ToggleButton.UncheckedEvent`; `null` raises `ToggleButton.IndeterminateEvent`.
#### `GetIsThreeState(DependencyObject d) -> bool`
Returns whether the target supports three-state behavior (true/false/null).
#### `SetIsThreeState(DependencyObject d, bool value)`
Enables or disables three-state mode. When `true`, `IsLocked` can be set to `null` as a third state.
#### `GetIsVirtualToggleButton(DependencyObject d) -> bool`
Returns whether the target is currently acting as a virtual toggle button.
#### `SetIsVirtualToggleButton(DependencyObject d, bool value)`
When set to `true`, attaches `MouseLeftButtonDown` and `KeyDown` handlers to the target (must implement `IInputElement`). When set to `false`, detaches these handlers.
### Internal Methods
#### `RaiseCheckedEvent(UIElement target) -> RoutedEventArgs`
Raises `ToggleButton.CheckedEvent` on the target element. Returns `null` if target is null.
#### `RaiseUncheckedEvent(UIElement target) -> RoutedEventArgs`
Raises `ToggleButton.UncheckedEvent` on the target element. Returns `null` if target is null.
#### `RaiseIndeterminateEvent(UIElement target) -> RoutedEventArgs`
Raises `ToggleButton.IndeterminateEvent` on the target element. Returns `null` if target is null.
---
## 3. Invariants
1. **Two-way binding by default**: `IsLockedProperty` is registered with `BindsTwoWayByDefault`, so bindings will update the source automatically.
2. **Event attachment requirement**: `IsVirtualToggleButton` only attaches event handlers if the target implements `IInputElement`. Non-`IInputElement` targets are silently ignored.
3. **Event raising requirement**: `RaiseEvent()` only works for targets that are either `UIElement` or `ContentElement`. Other `DependencyObject` types will not raise events.
4. **Toggle cycle behavior**:
- When `IsThreeState` is `false`: toggles between `true` and `false` only.
- When `IsThreeState` is `true`: cycles through `false``true``null``false`.
5. **Keyboard handling constraints**:
- Space key is ignored when Alt modifier is present (to avoid interfering with system menu).
- Enter key only triggers toggle if `KeyboardNavigation.AcceptsReturnProperty` is `true` on the sender.
6. **Event source filtering**: `OnKeyDown` only processes events where `e.OriginalSource == sender`, preventing handling of bubbled events from child elements.
---
## 4. Dependencies
### This module depends on:
- `System` (core types)
- `System.Windows` (`DependencyObject`, `DependencyProperty`, `FrameworkPropertyMetadata`, `UIElement`, `ContentElement`, `RoutedEventArgs`, `IInputElement`)
- `System.Windows.Controls.Primitives` (`ToggleButton` - for `CheckedEvent`, `UncheckedEvent`, `IndeterminateEvent`)
- `System.Windows.Input` (`Key`, `KeyEventArgs`, `Keyboard`, `KeyboardNavigation`, `ModifierKeys`, `MouseButtonEventArgs`)
### Consumers:
- Unclear from source alone. Any XAML or code in the `DTS.Viewer.GraphList` namespace or referencing it may use these attached properties.
---
## 5. Gotchas
1. **Misleading XML documentation**: The XML comments for `IsLocked` state "indicates whether the toggle button is checked" — this appears to be copy-pasted from a standard `ToggleButton` implementation. The property is named `IsLocked`, not `IsChecked`, which may indicate domain-specific semantics (e.g., locking a graph item vs. selecting it).
2. **Type mismatch between event raising methods**: `RaiseCheckedEvent`, `RaiseUncheckedEvent`, and `RaiseIndeterminateEvent` accept only `UIElement`, but the private `RaiseEvent` helper supports both `UIElement` and `ContentElement`. If a `ContentElement` has `IsLocked` set, the change handler will attempt to raise events on it via `RaiseEvent`, but the public `RaiseXxxEvent` methods cannot be called with `ContentElement` directly.
3. **Null return from event methods**: The `RaiseXxxEvent` methods return `null` when the target is null, but they do not throw. Callers should check for null if they intend to use the returned `RoutedEventArgs`.
4. **Local variable shadows property name**: In `UpdateIsLocked()`, the local variable is named `IsLocked`, which shadows the property accessor method naming convention. This is legal but could cause confusion during debugging.
5. **No validation of IsThreeState consistency**: Setting `IsLocked` to `null` is always possible regardless of `IsThreeState` value. The `IsThreeState` property only affects toggle behavior in `UpdateIsLocked()`, not direct programmatic assignment.