Files
DP44/enriched-qwen3-coder-next/DataPRO/Modules/RegionOfInterest/RegionOfInterestChannels/View.md
2026-04-17 14:55:32 -04:00

172 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/Modules/RegionOfInterest/RegionOfInterestChannels/View/StateListIndexConverter.cs
- DataPRO/Modules/RegionOfInterest/RegionOfInterestChannels/View/RegionOfInterestChannelsView.xaml.cs
- DataPRO/Modules/RegionOfInterest/RegionOfInterestChannels/View/RegionOfInterestChannelsDataTemplateSelector.cs
- DataPRO/Modules/RegionOfInterest/RegionOfInterestChannels/View/GridViewColumns.cs
generated_at: "2026-04-16T04:34:31.801575+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "b5797f8ba3342db7"
---
# View
## Documentation: RegionOfInterestChannels View Layer
---
### 1. Purpose
This module provides WPF UI infrastructure for rendering and interacting with a `GridView`-based view of region-of-interest (ROI) channel data. It enables dynamic column generation from a data source, per-column type-aware cell templating (e.g., `TextBlock` vs. `CheckBox`), column header interactivity (sorting, filtering, multi-select), and automatic column width adjustment for content-fit. It serves as the view layer in an MVVM pattern, implementing `IRegionOfInterestChannelsView` and delegating user actions to an associated `IRegionOfInterestChannelsViewModel`.
---
### 2. Public Interface
#### `StateListIndexConverter`
**Namespace:** `RegionOfInterestChannels`
**Implements:** `IMultiValueConverter`
- **`Convert(object[] values, Type targetType, object parameter, CultureInfo culture)`**
Converts a 2-element multi-value binding: expects `[0] = IEnumerable<State>`, `[1] = int index`. Returns the `State` at the given index in the collection, or `null` if inputs are invalid or index is out of bounds.
**Note:** Does *not* support `ConvertBack`.
#### `RegionOfInterestChannelsView`
**Namespace:** `RegionOfInterestChannels`
**Implements:** `IRegionOfInterestChannelsView` (partial class)
- **`RegionOfInterestChannelsView()`**
Constructor; calls `InitializeComponent()`.
- **`GridViewColumnHeader_OnClick(object sender, RoutedEventArgs e)`**
Handles column header click events. Extracts the `Tag` from the clicked header (supporting `GridViewColumnHeaderSearchable` or `GridViewColumnHeaderSelectable` types), then invokes `vm.Sort(columnTag, true)` on the `DataContext` if it implements `IRegionOfInterestChannelsViewModel`.
- **`TextBlock_Loaded(object sender, RoutedEventArgs e)`**
Adjusts column width dynamically when a `TextBlock` in a cell is loaded and its content width exceeds the columns current width (only if `Width` is `double.NaN`). Finds the column index via visual tree traversal and temporarily sets `Width = ActualWidth`, then resets to `NaN` to trigger remeasurement.
#### `RegionOfInterestChannelsDataTemplateSelector`
**Namespace:** `RegionOfInterestChannels`
**Inherits:** `DataTemplateSelector`
- **`TextBlockDataTemplate` / `CheckBoxDataTemplate`**
Public properties for the two templates to select between.
- **`SelectTemplate(object item, DependencyObject container)`**
Selects a `DataTemplate` based on the cells underlying data type:
- If `item` is a `ChannelEnabler`, inspects the columns header (as property name) to determine the property type on `item`.
- If type is `string` → returns `TextBlockDataTemplate`; sets `ContentPresenter.Tag` to the property value.
- If type is `boolean` (or other) → returns `CheckBoxDataTemplate`; sets `ContentPresenter.Tag` to the *relative index* of the column among boolean columns (`i - checkStartColumn`).
- If `item` is not a `ChannelEnabler`, defaults to `TextBlockDataTemplate`.
**Note:** Uses reflection (`GetProperty`, `GetValue`, `GetType`) on the `item` and `presenter.Columns[i].Header`. Assumes header text matches property names (with spaces removed).
#### `GridViewColumns` (Static Class)
**Namespace:** `RegionOfInterestChannels`
**Purpose:** Attached property provider for configuring `GridView` columns dynamically from an `ICollectionView` source.
##### Attached Properties:
- **`ColumnsSource`** (`object`)
Source collection (typically `ICollectionView`) whose items define columns. Changing this clears and recreates columns.
- **`CellDataTemplateSelector`** (`DataTemplateSelector`)
Optional selector used to choose per-cell templates.
- **`CellDataTemplate`** (`DataTemplate`)
Fallback template for cells if `CellDataTemplateSelector` is `null`.
- **`HeaderTextMember`** (`string`)
Property name on column source items whose value is used for column header text.
- **`DisplayMember`** (`string`)
Property name on column source items whose value is used as the binding path for cell content (currently commented out in `CreateColumn`).
##### Key Methods (Internal/Static):
- **`CreateColumn(GridView gridView, object columnSource)`**
Constructs a `GridViewColumn` from a `columnSource` item:
- Reads `HeaderTextMember` and `DisplayMember` from `gridView`.
- Determines column header type based on the *column source items* `MemberType` property (retrieved via `GetPropertyValue(columnSource, "MemberType")`):
- `typeof(bool)``GridViewColumnHeaderSelectable` with `SelectAll` event handler.
- `typeof(string)``GridViewColumnHeaderSearchable` with `Search` and `ClickHandler` events.
- Otherwise → plain `string` header.
- Assigns `CellTemplateSelector`, `CellTemplate`, and (commented-out) `DisplayMemberBinding`.
- **`GetPropertyValue(object obj, string propertyName)`**
Helper: uses reflection to get `propertyName` from `obj`.
- **`GetArrayIndex(string fromString)`**
Parses an integer from a string like `"SomeProperty[3]"`, returning `-1` on failure.
##### Event Handlers (Internal):
- **`ColumnsSource_CollectionChanged(...)`**
Syncs `gridView.Columns` with changes (`Add`, `Remove`, `Replace`, `Move`, `Reset`) in the `ColumnsSource` collection.
- **`GridViewColumnHeaderSearchable_OnSearch(...)`**
Invokes `vm.Filter(columnTag, searchTerm)`.
- **`GridViewColumnHeader_OnClick(...)`**
Invokes `vm.Sort(columnTag, true)` (same behavior as `RegionOfInterestChannelsView.GridViewColumnHeader_OnClick`).
- **`GridViewColumnHeaderSelectable_OnSelectAll(...)`**
Parses column index from `columnTag` (e.g., `"Enabled[2]"`), then invokes `vm.SelectAll(columnIndex, isSelected)`.
---
### 3. Invariants
- **Column Source Contract:**
Items in the `ColumnsSource` collection must have:
- A property named `"MemberType"` (e.g., `typeof(string)` or `typeof(bool)`), used to determine header type.
- Properties named by `HeaderTextMember` and `DisplayMember` (if set), or default to `null`.
- **Header Tag Format:**
For `GridViewColumnHeaderSelectable`, the `Tag` must be a string containing an array index in brackets (e.g., `"Enabled[0]"`) to be parsed by `GetArrayIndex`.
- **`StateListIndexConverter` Input Expectation:**
Exactly two values: an `IEnumerable<State>` and an `int`. Any deviation yields `null`.
- **`ChannelEnabler` Assumption:**
`RegionOfInterestChannelsDataTemplateSelector.SelectTemplate` assumes `item` is a `ChannelEnabler` when inspecting property types. Behavior for other types is not defined in source.
- **Column Width Adjustment Scope:**
`TextBlock_Loaded` only adjusts the *first* matching `ContentPresenter` in the row. If multiple `TextBlock`s exist per row, only the first is considered.
---
### 4. Dependencies
#### Dependencies *of* this module:
- **WPF Framework:** `System.Windows`, `System.Windows.Controls`, `System.Windows.Data`, `System.Windows.Media`.
- **Common Libraries:**
- `DTS.Common.Controls` (for `GridViewColumnHeaderSearchable`, `GridViewColumnHeaderSelectable`)
- `DTS.Common.Interface.RegionOfInterest.RegionOfInterestChannels` (for `IRegionOfInterestChannelsView`, `IRegionOfInterestChannelsViewModel`)
- `DTS.Common.Utils` (for `Utils.FindChild<T>`)
#### Dependencies *on* this module:
- **`IRegionOfInterestChannelsViewModel`** must be implemented by the `DataContext` for `RegionOfInterestChannelsView` to handle sorting, filtering, and selection.
- **`State` type** is used by `StateListIndexConverter` (imported from elsewhere in the codebase).
- **`ChannelEnabler` type** is used by `RegionOfInterestChannelsDataTemplateSelector` (imported from elsewhere).
---
### 5. Gotchas
- **`ConvertBack` is Unimplemented:**
`StateListIndexConverter.ConvertBack` throws `NotImplementedException`. It is strictly a one-way converter.
- **`DisplayMemberBinding` is Commented Out:**
In `CreateColumn`, the line setting `column.DisplayMemberBinding` is commented. Cell binding relies entirely on `CellDataTemplateSelector` or `CellDataTemplate`. This may cause confusion if `DisplayMember` is set but unused.
- **Header Property Name Matching:**
`RegionOfInterestChannelsDataTemplateSelector.SelectTemplate` uses `presenter.Columns[i].Header.ToString().Replace(" ", "")` to match property names. If headers contain non-alphanumeric characters beyond spaces, reflection will fail.
- **`MemberType` Property Requirement:**
Column source items *must* expose a `"MemberType"` property (via reflection). If missing or non-`Type`, `columnPropertyType` becomes `null`, causing `checkStartColumn` to be set and defaulting to `CheckBoxDataTemplate`.
- **Duplicate Event Handlers Risk:**
`ColumnsSource_CollectionChanged` adds handlers to `ICollectionView.CollectionChanged` but does not deduplicate if `ColumnsSource` is reassigned to the *same* collection instance. This could lead to multiple handler invocations per event.
- **`TextBlock_Loaded` Fragility:**
Relies on a specific visual tree structure (`GridViewRowPresenter``ContentPresenter``TextBlock`). Changes to control templates may break the width adjustment logic.
- **No Null-Safety for `e?.OriginalSource`:**
In `GridViewColumnHeaderSelectable_OnSelectAll`, `(bool)(e?.OriginalSource ?? false)` may throw `InvalidCastException` if `e.OriginalSource` is not a `bool` or `null`.