From 7dec26b1ac84ea40c8b4acea70872095e9a2c858 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Thu, 4 Jun 2026 21:42:07 +0800 Subject: [PATCH] fix: replace RowStyle IsSelected binding with SelectionChanged event - RowStyle TwoWay binding on IsSelected is unreliable with virtualizing DataGrid - Switched to DataGrid.SelectionChanged event handler in code-behind - Syncs RemovedItems/AddedItems to ViewModel.IsSelected reliably --- src/UI/WPF/Views/PathEditingView.xaml | 8 +-- src/UI/WPF/Views/PathEditingView.xaml.cs | 76 ++++++++++++++---------- 2 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/UI/WPF/Views/PathEditingView.xaml b/src/UI/WPF/Views/PathEditingView.xaml index 0b08031..9960293 100644 --- a/src/UI/WPF/Views/PathEditingView.xaml +++ b/src/UI/WPF/Views/PathEditingView.xaml @@ -42,11 +42,6 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管 - - - @@ -241,13 +236,12 @@ NavisworksTransport 路径编辑页签视图 - 采用与动画控制和分层管 - - /// ViewModel属性,用于外部访问 + /// ViewModel属性,用于外部访问 /// public PathEditingViewModel ViewModel { get; private set; } - + /// /// 时标服务实例 /// private TimeTagService _timeTagService; /// - /// 构造函数,需要传入主ViewModel以支持统一状态栏 + /// 构造函数,需要传入主ViewModel以支持统一状态栏 /// - /// 主ViewModel,用于统一状态栏 + /// 主ViewModel,用于统一状态栏 public PathEditingView(LogisticsControlViewModel mainViewModel) { InitializeComponent(); - - // 创建ViewModel,传入主ViewModel引用 + + // 创建ViewModel,传入主ViewModel引用 ViewModel = new PathEditingViewModel(mainViewModel); DataContext = ViewModel; - + + PathRoutesGrid.SelectionChanged += OnPathRoutesSelectionChanged; + LogManager.Info("PathEditingView初始化完成 - 支持统一状态栏"); } + /// + /// 同步 DataGrid 多选状态到 ViewModel 的 IsSelected + /// + private void OnPathRoutesSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (ViewModel?.PathRoutes == null) return; + + foreach (PathRouteViewModel item in e.RemovedItems) + item.IsSelected = false; + + foreach (PathRouteViewModel item in e.AddedItems) + item.IsSelected = true; + } + /// /// 清理资源 /// @@ -50,7 +66,7 @@ namespace NavisworksTransport.UI.WPF.Views { // 清理ViewModel ViewModel?.Cleanup(); - + LogManager.Info("PathEditingView资源清理完成"); } catch (Exception ex) @@ -60,14 +76,14 @@ namespace NavisworksTransport.UI.WPF.Views } /// - /// 路径列表中"时标"按钮点击,打开时间标签窗口 + /// 路径列表中"时标"按钮点击,打开时间标签窗口 /// private void OnTimeTagButtonClick(object sender, RoutedEventArgs e) { try { LogManager.Info("时标按钮被点击"); - + // 从按钮的DataContext获取当前路径ViewModel if (!(sender is Button button) || !(button.DataContext is PathRouteViewModel routeVm)) { @@ -82,7 +98,7 @@ namespace NavisworksTransport.UI.WPF.Views LogManager.Warning("PathRouteViewModel中的Route为空"); return; } - + // 确保服务已初始化 if (_timeTagService == null) { @@ -91,13 +107,13 @@ namespace NavisworksTransport.UI.WPF.Views var db = pathManager.GetPathDatabase(); if (db == null) { - throw new InvalidOperationException("时标服务初始化失败:无法获取数据库实例"); + throw new InvalidOperationException("时标服务初始化失败:无法获取数据库实例"); } _timeTagService = new TimeTagService(db); LogManager.Info("时标服务已初始化"); } - + // 创建并显示时标对话框 var dlg = new TimeTagDialog(_timeTagService, route); DialogHelper.SetOwnerFromUserControl(dlg, this); @@ -112,17 +128,17 @@ namespace NavisworksTransport.UI.WPF.Views MessageBox.Show($"打开时标窗口失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } - + /// - /// 路径分析按钮点击事件,打开路径规划分析对话框(非模态) + /// 路径分析按钮点击事件,打开路径规划分析对话框(非模态) /// private void OnPathAnalysisButtonClick(object sender, RoutedEventArgs e) { try { - LogManager.Info("路径分析按钮被点击,准备打开PathAnalysisDialog窗口"); - - // 使用静态方法显示(单例模式,非模态) + LogManager.Info("路径分析按钮被点击,准备打开PathAnalysisDialog窗口"); + + // 使用静态方法显示(单例模式,非模态) var parentWindow = Window.GetWindow(this); PathAnalysisDialog.ShowAnalysis(parentWindow); } @@ -134,18 +150,18 @@ namespace NavisworksTransport.UI.WPF.Views } /// - /// 生成导航地图按钮点击事件,打开生成导航地图对话框 + /// 生成导航地图按钮点击事件,打开生成导航地图对话框 /// private void OnGenerateNavigationMapButtonClick(object sender, RoutedEventArgs e) { try { - LogManager.Info("生成导航地图按钮被点击,准备打开GenerateNavigationMapDialog窗口"); + LogManager.Info("生成导航地图按钮被点击,准备打开GenerateNavigationMapDialog窗口"); // 检查前置条件 if (ViewModel?.SelectedPathRoute == null || ViewModel.SelectedPathRoute.Points.Count == 0) { - LogManager.Warning("无法生成导航地图:未选择路径或路径为空"); + LogManager.Warning("无法生成导航地图:未选择路径或路径为空"); return; } @@ -235,32 +251,32 @@ namespace NavisworksTransport.UI.WPF.Views } /// - /// 测量包围盒按钮点击事件,打开元素包围盒信息窗口 + /// 测量包围盒按钮点击事件,打开元素包围盒信息窗口 /// private void OnMeasureBoundsButtonClick(object sender, RoutedEventArgs e) { try { - LogManager.Info("测量包围盒按钮被点击,准备打开ModelItemBoundsWindow窗口"); + LogManager.Info("测量包围盒按钮被点击,准备打开ModelItemBoundsWindow窗口"); // 创建或复用窗口实例 if (_boundsWindow == null || !_boundsWindow.IsVisible) { _boundsWindow = new ModelItemBoundsWindow(); - - // 设置父窗口(非模态窗口) + + // 设置父窗口(非模态窗口) DialogHelper.SetOwnerFromUserControl(_boundsWindow, this); - // 使用 Show() 而非 ShowDialog(),允许窗口一直开着 + // 使用 Show() 而非 ShowDialog(),允许窗口一直开着 _boundsWindow.Show(); - LogManager.Info("ModelItemBoundsWindow窗口已显示(非模态)"); + LogManager.Info("ModelItemBoundsWindow窗口已显示(非模态)"); } else { - // 窗口已存在,刷新信息并激活 + // 窗口已存在,刷新信息并激活 _boundsWindow.RefreshBoundsInfo(); _boundsWindow.Activate(); - LogManager.Info("ModelItemBoundsWindow窗口已存在,已刷新并激活"); + LogManager.Info("ModelItemBoundsWindow窗口已存在,已刷新并激活"); } } catch (Exception ex) @@ -271,7 +287,7 @@ namespace NavisworksTransport.UI.WPF.Views } /// - /// 包围盒信息窗口实例(保持引用以防止被GC回收) + /// 包围盒信息窗口实例(保持引用以防止被GC回收) /// private ModelItemBoundsWindow _boundsWindow; }