Convert sensor pane scaffold and TreeView to MainWindow.xaml (Phase 5b step 4)

Declare the sensor pane (SensorPane), header host (SensorHeaderHost), and TreeView (SensorTree, with its ContentPresenter DataTemplate and SelectionChanged handler) in XAML. The measurer-managed header grid and the per-row CreateSensorRow content remain imperative since they involve dynamic column-width pushing and per-item context flyouts/double-tap handlers; this is the hybrid fallback called out in the Phase 5b plan.

Drop _sensorTree/_sensorPane fields; replace BuildSensorPane with a small PopulateSensorHeader and delete the old XamlReader-loaded DataTemplate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-06-02 13:31:24 -05:00
co-authored by Copilot
parent c6ef3edeff
commit fd55a89e22
2 changed files with 26 additions and 56 deletions
@@ -36,8 +36,6 @@ public sealed partial class MainWindow : Window
private readonly DispatcherQueueTimer _timer;
private readonly PlotView _plotView;
private readonly Grid _plotPane;
private readonly TreeView _sensorTree;
private readonly Grid _sensorPane;
private readonly WinUiStartupTrace? _startupTrace;
private readonly TrayIconService _trayIconService;
private readonly DialogService _dialogService;
@@ -96,17 +94,7 @@ public sealed partial class MainWindow : Window
Bind(ContentGrid, UIElement.IsHitTestVisibleProperty, ViewModel, nameof(ViewModel.IsHardwareInteractionEnabled));
MeasureStartup("MainWindow.PopulateMenuSubmenus", PopulateMenuSubmenus);
TreeView? builtTree = null;
Grid sensorPane = MeasureStartup("MainWindow.BuildSensorPane", () =>
{
Grid pane = BuildSensorPane(out TreeView tree);
builtTree = tree;
return pane;
});
_sensorPane = sensorPane;
_sensorTree = builtTree!;
ContentGrid.Children.Add(sensorPane);
MeasureStartup("MainWindow.PopulateSensorHeader", PopulateSensorHeader);
PlotView? builtPlot = null;
Grid plotPane = MeasureStartup("MainWindow.BuildPlotPane", () =>
@@ -226,7 +214,7 @@ public sealed partial class MainWindow : Window
private string GetRootSizeDetail()
{
return FormattableString.Invariant($"root={RootGrid.ActualWidth:F0}x{RootGrid.ActualHeight:F0}, rows={_columnMeasurer.RowCount}, rootNodes={_sensorTree.RootNodes.Count}");
return FormattableString.Invariant($"root={RootGrid.ActualWidth:F0}x{RootGrid.ActualHeight:F0}, rows={_columnMeasurer.RowCount}, rootNodes={SensorTree.RootNodes.Count}");
}
private void RootGrid_Loaded(object sender, RoutedEventArgs e)
@@ -371,17 +359,8 @@ public sealed partial class MainWindow : Window
private async void OnWebServerAuthentication(object sender, RoutedEventArgs e) => await _dialogService.ShowWebServerAuthenticationAsync();
private async void OnAbout(object sender, RoutedEventArgs e) => await _dialogService.ShowAboutAsync();
private Grid BuildSensorPane(out TreeView tree)
private void PopulateSensorHeader()
{
Grid pane = new()
{
RowDefinitions =
{
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }
}
};
Grid header = _columnMeasurer.CreateHeaderGrid();
header.Padding = new Thickness(8, 5, 8, 5);
header.Background = (Brush)Application.Current.Resources["SystemControlBackgroundChromeMediumLowBrush"];
@@ -389,20 +368,7 @@ public sealed partial class MainWindow : Window
header.Children.Add(CreateHeaderText("Value", 1, ViewModel.ValueColumnVisibility, nameof(ViewModel.ValueColumnVisibility)));
header.Children.Add(CreateHeaderText("Min", 2, ViewModel.MinColumnVisibility, nameof(ViewModel.MinColumnVisibility)));
header.Children.Add(CreateHeaderText("Max", 3, ViewModel.MaxColumnVisibility, nameof(ViewModel.MaxColumnVisibility)));
pane.Children.Add(header);
Grid treeHost = new();
Grid.SetRow(treeHost, 1);
tree = new()
{
ItemTemplate = CreateTreeViewNodeContentTemplate(),
SelectionMode = TreeViewSelectionMode.Single
};
tree.SelectionChanged += SensorTree_SelectionChanged;
treeHost.Children.Add(tree);
pane.Children.Add(treeHost);
return pane;
SensorHeaderHost.Children.Add(header);
}
private Grid BuildPlotPane(out PlotView plotView)
@@ -636,16 +602,13 @@ public sealed partial class MainWindow : Window
private void RebuildSensorTreeCore()
{
if (_sensorTree == null)
return;
_columnMeasurer.ResetRows();
_sensorTree.RootNodes.Clear();
SensorTree.RootNodes.Clear();
foreach (SensorTreeItemViewModel item in ViewModel.RootItems)
{
TreeViewNode? node = CreateTreeNode(item);
if (node != null)
_sensorTree.RootNodes.Add(node);
SensorTree.RootNodes.Add(node);
}
UpdateSensorColumnWidths();
@@ -667,17 +630,6 @@ public sealed partial class MainWindow : Window
CompleteStartupTraceIfReady();
}
private static DataTemplate CreateTreeViewNodeContentTemplate()
{
const string xaml = """
<DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ContentPresenter Content="{Binding Content}" />
</DataTemplate>
""";
return (DataTemplate)XamlReader.Load(xaml);
}
private TreeViewNode? CreateTreeNode(SensorTreeItemViewModel item)
{
if (item.RowVisibility == Visibility.Collapsed)
@@ -881,8 +833,8 @@ public sealed partial class MainWindow : Window
Grid.SetColumn(_plotPane, ViewModel.PlotGridColumn);
Grid.SetRowSpan(_plotPane, ViewModel.PlotGridRowSpan);
Grid.SetColumnSpan(_plotPane, ViewModel.PlotGridColumnSpan);
Grid.SetRowSpan(_sensorPane, ViewModel.SensorGridRowSpan);
Grid.SetColumnSpan(_sensorPane, ViewModel.SensorGridColumnSpan);
Grid.SetRowSpan(SensorPane, ViewModel.SensorGridRowSpan);
Grid.SetColumnSpan(SensorPane, ViewModel.SensorGridColumnSpan);
UpdatePlotWindowVisibility();
DrawPlot();
}
@@ -87,6 +87,24 @@
<RowDefinition Height="*" />
<RowDefinition Height="220" />
</Grid.RowDefinitions>
<Grid x:Name="SensorPane" Grid.Column="0" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="SensorHeaderHost" Grid.Row="0" />
<Grid Grid.Row="1">
<TreeView x:Name="SensorTree"
SelectionMode="Single"
SelectionChanged="SensorTree_SelectionChanged">
<TreeView.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Content}" />
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Grid>
</Grid>
<TextBlock x:Name="StatusText"
Grid.Row="2"