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;
}