diff --git a/DeviceEditModule/ViewModels/DialogMangerViewModel.cs b/DeviceEditModule/ViewModels/DialogMangerViewModel.cs
index 1d29cdd..eab5e53 100644
--- a/DeviceEditModule/ViewModels/DialogMangerViewModel.cs
+++ b/DeviceEditModule/ViewModels/DialogMangerViewModel.cs
@@ -27,7 +27,7 @@ namespace DeviceEditModule.ViewModels
/// 所有 Tab 项集合,绑定到标签条的 ItemsControl。
public ObservableCollection TagItems { get; } = new();
- /// 以 Tab 标题为 key 追踪已打开的 Tab,防止重复打开。
+ /// 以设备指纹为 key 追踪已打开的 Tab,防止同一物理设备重复打开。
private readonly Dictionary _tabDictionary = new();
private DialogTabItemVM? _selectedTag;
@@ -87,11 +87,11 @@ namespace DeviceEditModule.ViewModels
#region Tab 管理
- /// 收到事件:若 Tab 已存在则激活,否则创建并追加到集合。
+ /// 收到事件:若指纹已存在则激活,否则创建并追加到集合。
private void OnAddTab(DialogTabInfo info)
{
- // 已有相同标题的 Tab → 直接激活,不重复创建
- if (_tabDictionary.TryGetValue(info.Title, out var existing))
+ // 已有相同指纹的 Tab → 直接激活,不重复创建
+ if (!string.IsNullOrEmpty(info.Fingerprint) && _tabDictionary.TryGetValue(info.Fingerprint, out var existing))
{
ActivateTab(existing);
return;
@@ -99,11 +99,14 @@ namespace DeviceEditModule.ViewModels
var tab = new DialogTabItemVM(OnSelectTab, OnCloseTab)
{
- Title = info.Title,
- Content = info.Content
+ Title = info.Title,
+ Fingerprint = info.Fingerprint,
+ Content = info.Content
};
- _tabDictionary[info.Title] = tab;
+ if (!string.IsNullOrEmpty(info.Fingerprint))
+ _tabDictionary[info.Fingerprint] = tab;
+
TagItems.Add(tab);
RaisePropertyChanged(nameof(HasNoTabs));
ActivateTab(tab);
@@ -116,7 +119,8 @@ namespace DeviceEditModule.ViewModels
private void OnCloseTab(DialogTabItemVM tab)
{
int idx = TagItems.IndexOf(tab);
- _tabDictionary.Remove(tab.Title);
+ if (!string.IsNullOrEmpty(tab.Fingerprint))
+ _tabDictionary.Remove(tab.Fingerprint);
TagItems.Remove(tab);
RaisePropertyChanged(nameof(HasNoTabs));
diff --git a/TestingModule/ViewModels/ParametersManagerViewModel.cs b/TestingModule/ViewModels/ParametersManagerViewModel.cs
index f5cf47a..7f7f61d 100644
--- a/TestingModule/ViewModels/ParametersManagerViewModel.cs
+++ b/TestingModule/ViewModels/ParametersManagerViewModel.cs
@@ -147,11 +147,14 @@ namespace TestingModule.ViewModels
}
// 4. 发布事件 → DialogMangerViewModel 接收后将此 View 添加为 Tab
- // 标题格式:{当前作用域} - {设备名称},作为全局唯一 Tab 标识
+ // 标题格式:{当前作用域} - {设备名称}
+ // 去重依据:设备硬件指纹(同一物理设备不重复打开)
+ var fingerprint = DeviceManager.ExtractHardwareFingerprint(SelectedDevice);
_eventAggregator.GetEvent().Publish(new DialogTabInfo
{
- Title = $"{_globalInfo.CurrentScope} - {SelectedDevice.DeviceName}",
- Content = view
+ Title = $"{_globalInfo.CurrentScope} - {SelectedDevice.DeviceName}",
+ Fingerprint = fingerprint,
+ Content = view
});
// 5. 将窗口置顶(确保用户看到新增的 Tab)
diff --git a/UIShare/GlobalVariable/DeviceManager.cs b/UIShare/GlobalVariable/DeviceManager.cs
index 3202aa8..2a9fa7e 100644
--- a/UIShare/GlobalVariable/DeviceManager.cs
+++ b/UIShare/GlobalVariable/DeviceManager.cs
@@ -38,7 +38,7 @@ namespace UIShare.GlobalVariable
/// 根据设备配置提取唯一的硬件指纹字符串。
/// Tcp → "Tcp:IP:Port";Serial → "Serial:PortName";无法识别则返回空字符串。
///
- private static string ExtractHardwareFingerprint(DeviceInfoVM config)
+ public static string ExtractHardwareFingerprint(DeviceInfoVM config)
{
if (string.Equals(config.ConnectionType, "Tcp", StringComparison.OrdinalIgnoreCase)
&& config.TcpConfig != null)
diff --git a/UIShare/UIViewModel/DialogTabInfo.cs b/UIShare/UIViewModel/DialogTabInfo.cs
index d8b5e5b..1ef06b4 100644
--- a/UIShare/UIViewModel/DialogTabInfo.cs
+++ b/UIShare/UIViewModel/DialogTabInfo.cs
@@ -10,6 +10,12 @@ namespace UIShare.UIViewModel
/// Tab 标题(显示在标签页上)。
public string Title { get; set; } = string.Empty;
+ ///
+ /// 设备硬件指纹(如 "Tcp:192.168.1.100:502"),用于去重判断,
+ /// 防止同一物理设备被重复打开多个 Tab。
+ ///
+ public string Fingerprint { get; set; } = string.Empty;
+
///
/// Tab 内容:传入一个已实例化的 (通常是 UserControl),
/// 由 ContentControl 直接承载展示。
diff --git a/UIShare/UIViewModel/DialogTabItemVM.cs b/UIShare/UIViewModel/DialogTabItemVM.cs
index ff86357..b09fc32 100644
--- a/UIShare/UIViewModel/DialogTabItemVM.cs
+++ b/UIShare/UIViewModel/DialogTabItemVM.cs
@@ -21,6 +21,14 @@ namespace DeviceEditModule.ViewModels
set => SetProperty(ref _title, value);
}
+ private string _fingerprint = string.Empty;
+ /// 设备硬件指纹,用于去重字典的 Key。
+ public string Fingerprint
+ {
+ get => _fingerprint;
+ set => SetProperty(ref _fingerprint, value);
+ }
+
private object? _content;
/// Tab 内容区域(通常为 UserControl 实例)。
public object? Content