feat(navigation): 重构导航系统引入导航参数和类型

- 新增NavigationType枚举定义导航类型
 - 新增NavigationParameter类用于传递导航参数
 - 重构INavigationService和INavigatable接口
 - 更新NavigationService实现以支持新的导航方式
 - 更新DeviceDetailViewModel, DevicesViewModel, VariableHistoryViewModel, VariableTableViewModel, MqttsViewModel等
 - 使ViewModelBase实现INavigatable接口
 - 更新MainView中的菜单选择导航逻辑
 - 优化VariableHistoryView界面布局,添加返回变量表按钮
This commit is contained in:
2025-10-03 22:28:58 +08:00
parent 1dbae9c208
commit 609c4741c1
14 changed files with 259 additions and 241 deletions

View File

@@ -5,6 +5,7 @@ using Dm;
using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Core.Enums;
using DMS.Core.Models;
using DMS.WPF.Services;
using DMS.Services;
using DMS.WPF.Interfaces;
@@ -14,7 +15,7 @@ using iNKORE.UI.WPF.Modern.Common.IconKeys;
namespace DMS.WPF.ViewModels;
public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
public partial class DeviceDetailViewModel : ViewModelBase
{
private readonly IMapper _mapper;
private readonly IDialogService _dialogService;
@@ -70,7 +71,7 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
{
Header = variableTableItemViewModel.Name,
Icon = SegoeFluentIcons.DataSense.Glyph,
TargetViewKey = "VariableTableView"
TargetViewKey = nameof(VariableTableViewModel)
};
int addVarTableId = await _wpfDataService.VariableTableDataService.AddVariableTable(
_mapper.Map<VariableTableDto>(variableTableItemViewModel),
@@ -187,9 +188,10 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
}
public async Task OnNavigatedToAsync(MenuItemViewModel menu)
public override async Task OnNavigatedToAsync(NavigationParameter parameter)
{
if (_dataStorageService.Devices.TryGetValue(menu.TargetId, out var device))
if (_dataStorageService.Devices.TryGetValue(parameter.TargetId, out var device))
{
CurrentDevice = device;
}
@@ -199,9 +201,12 @@ public partial class DeviceDetailViewModel : ViewModelBase, INavigatable
public void NavigateToVariableTable()
{
if (SelectedVariableTable == null) return;
var menu = _dataStorageService.Menus.FirstOrDefault(m => m.MenuType == MenuType.VariableTableMenu &&
m.TargetId == SelectedVariableTable.Id);
if (menu == null) return;
_navigationService.NavigateToAsync(menu);
// var menu = _dataStorageService.Menus.FirstOrDefault(m => m.MenuType == MenuType.VariableTableMenu &&
// m.TargetId == SelectedVariableTable.Id);
// if (menu == null) return;
_navigationService.NavigateToAsync(
this,
new NavigationParameter(nameof(VariableTableViewModel), SelectedVariableTable.Id,
NavigationType.VariableTable));
}
}

View File

@@ -6,6 +6,7 @@ using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Application.Interfaces.Database;
using DMS.Core.Enums;
using DMS.Core.Models;
using DMS.WPF.Interfaces;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Dialogs;
@@ -122,7 +123,7 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
{
Header = dto.VariableTable.Name,
Icon = SegoeFluentIcons.DataSense.Glyph,
TargetViewKey = "VariableTableView"
TargetViewKey = nameof(VariableTableViewModel)
};
}
@@ -241,16 +242,9 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
{
if (SelectedDevice == null) return;
var menu = _dataStorageService.Menus.FirstOrDefault(m => m.MenuType == MenuType.DeviceMenu &&
m.TargetId == SelectedDevice.Id);
if (menu == null) return;
_navigationService.NavigateToAsync(menu);
_navigationService.NavigateToAsync(this,new NavigationParameter(nameof(DeviceDetailViewModel),SelectedDevice.Id,NavigationType.Device));
}
public async Task OnNavigatedToAsync(MenuItemViewModel menu)
{
}
[RelayCommand]
private async Task AddVariableTable(DeviceItemViewModel device)
@@ -276,7 +270,7 @@ public partial class DevicesViewModel : ViewModelBase, INavigatable
{
Header = variableTableItemViewModel.Name,
Icon = SegoeFluentIcons.DataSense.Glyph,
TargetViewKey = "VariableTableView"
TargetViewKey = nameof(VariableTableViewModel)
};
int addVarTableId = await _wpfDataService.VariableTableDataService.AddVariableTable(
_mapper.Map<VariableTableDto>(variableTableItemViewModel),

View File

@@ -57,10 +57,6 @@ public partial class MainViewModel : ViewModelBase
CurrentViewModel = new HomeViewModel();
CurrentViewModel.OnLoaded();
// 发送消息加载数据
MessageHelper.SendLoadMessage(LoadTypes.All);
// 当菜单加载成功后,在前台显示菜单
// _dataServices.OnMenuTreeListChanged += (menus) => { Menus = new ObservableCollection<MenuBean>(menus); };
}
/// <summary>
@@ -84,86 +80,6 @@ public partial class MainViewModel : ViewModelBase
// Application.Current.Shutdown();
}
/// <summary>
/// 添加变量表。
/// </summary>
/// <param name="menu">当前菜单项,用于获取父级设备信息。</param>
private async Task AddVariableTable(MenuBean menu)
{
// var db = DbContext.GetInstance();
// try
// {
// // 1. 检查父级设备信息
// if (menu.Parent?.Data is not Device device)
// {
// _logger.LogWarning("尝试添加变量表时Parent 或 Parent.Data 为空,或 Parent.Data 不是 Device 类型。");
// NotificationHelper.ShowError("操作失败:无法获取有效的设备信息。");
// return;
// }
//
//
// // 2. 显示添加变量表对话框
// var varTable = await _dialogService.ShowAddVarTableDialog();
// if (varTable == null)
// {
// // 用户取消或未选择
// return;
// }
//
// // 3. 设置变量表属性
// varTable.IsActive = true;
// varTable.DeviceId = device.Id;
// varTable.ProtocolType = device.ProtocolType;
//
// // 4. 添加变量表到数据库
// // 假设 _varTableRepository.AddAsync 返回一个布尔值表示成功,或者一个表示 ID 的整数
// // 这里为了演示我们假设它返回新添加的ID如果失败则返回0
// await db.BeginTranAsync();
// var addVarTable = await _varTableRepository.AddAsync(varTable, db);
//
// // 5. 添加变量表菜单
// MenuBean newMenu = new MenuBean
// {
// Icon = SegoeFluentIcons.Tablet.Glyph,
// Name = varTable.Name,
// DataId = addVarTable.Id, // 使用实际添加的ID
// Type = MenuType.VariableTableMenu,
// ParentId = menu.Parent.Id
// };
//
// var addMenuRes = await _menuRepository.AddAsync(newMenu, db);
// if (addMenuRes > 0)
// {
// await db.CommitTranAsync();
// // 变量表和菜单都添加成功
// MessageHelper.SendLoadMessage(LoadTypes.Menu);
// MessageHelper.SendLoadMessage(LoadTypes.Devices);
// NotificationHelper.ShowSuccess($"变量表:{varTable.Name},添加成功");
// _logger.LogInformation($"变量表:{varTable.Name},添加成功");
// }
// else
// {
// await db.RollbackTranAsync();
// // 变量表菜单添加失败 (此时变量表可能已添加成功,需要根据业务决定是否回滚)
// NotificationHelper.ShowError($"变量表:{varTable.Name},添加菜单失败");
// _logger.LogError($"变量表:{varTable.Name},添加菜单失败");
// // 考虑:如果菜单添加失败,是否需要删除之前添加的变量表?
// // 例如await _varTableRepository.DeleteAsync(addVarTableId);
// }
// }
// catch (Exception e)
// {
// await db.RollbackTranAsync();
// NotificationHelper.ShowError($"添加变量表时出现了错误:{e.Message}", e);
// }
}
/// <summary>
/// 处理菜单选择变化的逻辑。
/// </summary>
/// <param name="menu">被选中的菜单项。</param>
public async Task MenuSelectionChanged(MenuItemViewModel menu)
{
_navigationService.NavigateToAsync(menu);
}
}

View File

@@ -6,6 +6,7 @@ using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Application.Interfaces.Database;
using DMS.Core.Enums;
using DMS.Core.Models;
using DMS.WPF.Interfaces;
using DMS.WPF.Services;
using DMS.WPF.ViewModels.Dialogs;
@@ -177,12 +178,13 @@ public partial class MqttsViewModel : ViewModelBase
}
// 导航到MQTT服务器详情页
var menu = new MenuItemViewModel
{
TargetViewKey = "MqttServerDetailView",
TargetId = SelectedMqtt.Id
};
await _navigationService.NavigateToAsync(menu);
// var menu = new MenuItemViewModel
// {
// TargetViewKey = "MqttServerDetailView",
// TargetId = SelectedMqtt.Id
// };
await _navigationService.NavigateToAsync(
this, new NavigationParameter(nameof(MqttServerDetailViewModel), SelectedMqtt.Id, NavigationType.Mqtt));
}
}

View File

@@ -6,7 +6,9 @@ using DMS.Application.DTOs;
using DMS.Application.Events;
using DMS.Application.Interfaces;
using DMS.Application.Interfaces.Database;
using DMS.Core.Enums;
using DMS.Core.Events;
using DMS.Core.Models;
using DMS.WPF.Interfaces;
using DMS.WPF.ViewModels.Items;
using LiveChartsCore;
@@ -28,6 +30,7 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
private readonly IDataStorageService _dataStorageService;
private readonly IEventService _eventService;
private readonly INotificationService _notificationService;
private readonly INavigationService _navigationService;
/// <summary>
/// 加载历史记录条数限制
@@ -83,8 +86,8 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
public VariableHistoryViewModel(IMapper mapper, IDialogService dialogService, IHistoryAppService historyAppService,
IWPFDataService wpfDataService, IDataStorageService dataStorageService,
IEventService eventService,
INotificationService notificationService)
IEventService eventService, INotificationService notificationService,
INavigationService navigationService)
{
_mapper = mapper;
_dialogService = dialogService;
@@ -93,6 +96,7 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
_dataStorageService = dataStorageService;
_eventService = eventService;
_notificationService = notificationService;
_navigationService = navigationService;
_variableHistoryList = new ObservableList<VariableHistoryDto>();
_variableHistorySynchronizedView = _variableHistoryList.CreateView(v => v);
@@ -168,9 +172,9 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
}
public async Task OnNavigatedToAsync(MenuItemViewModel menu)
public override async Task OnNavigatedToAsync(NavigationParameter parameter)
{
if (_dataStorageService.Variables.TryGetValue(menu.TargetId, out VariableItemViewModel variableItem))
if (_dataStorageService.Variables.TryGetValue(parameter.TargetId, out VariableItemViewModel variableItem))
{
CurrentVariable = variableItem;
// 加载所有变量的历史记录
@@ -190,6 +194,23 @@ partial class VariableHistoryViewModel : ViewModelBase, INavigatable
}
}
/// <summary>
/// 返回变量表命令
/// </summary>
[RelayCommand]
private async Task NavigateToVariableTable()
{
try
{
// 导航到变量表页面
await _navigationService.NavigateToAsync(this,new NavigationParameter(nameof(VariableTableViewModel),CurrentVariable.VariableTableId,NavigationType.VariableTable));
}
catch (Exception ex)
{
_notificationService.ShowError($"导航到变量表失败: {ex.Message}", ex);
}
}
/// <summary>
/// 根据搜索文本过滤历史记录

View File

@@ -739,11 +739,9 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
{
// 导航到历史记录视图
var navigationService = App.Current.Services.GetRequiredService<INavigationService>();
MenuItemViewModel viewModel = new MenuItemViewModel();
viewModel.TargetViewKey = "VariableHistoryView";
viewModel.MenuType = MenuType.VariableMenu;
viewModel.TargetId = SelectedVariable.Id;
navigationService.NavigateToAsync(viewModel);
navigationService.NavigateToAsync(
this,
new NavigationParameter(nameof(VariableHistoryViewModel), SelectedVariable.Id, NavigationType.Variable));
}
/// <summary>
@@ -875,9 +873,9 @@ partial class VariableTableViewModel : ViewModelBase, INavigatable
// }
}
public async Task OnNavigatedToAsync(MenuItemViewModel menu)
public override async Task OnNavigatedToAsync(NavigationParameter parameter)
{
if (_dataStorageService.VariableTables.TryGetValue(menu.TargetId, out var varTable))
if (_dataStorageService.VariableTables.TryGetValue(parameter.TargetId, out var varTable))
{
CurrentVariableTable = varTable;
// 根据变量表的协议类型设置对应的布尔属性

View File

@@ -1,8 +1,11 @@
using CommunityToolkit.Mvvm.ComponentModel;
using DMS.Core.Models;
using DMS.WPF.Interfaces;
using DMS.WPF.ViewModels.Items;
namespace DMS.WPF.ViewModels;
public abstract class ViewModelBase : ObservableObject
public abstract class ViewModelBase : ObservableObject,INavigatable
{
public virtual void OnLoaded()
{
@@ -20,5 +23,13 @@ public abstract class ViewModelBase : ObservableObject
}
public virtual async Task OnNavigatedToAsync(NavigationParameter parameter)
{
}
public virtual async Task OnNavigatedFromAsync(NavigationParameter parameter)
{
}
}