完成显示日志功能
This commit is contained in:
@@ -221,6 +221,7 @@ public partial class App : System.Windows.Application
|
||||
services.AddSingleton<IDataCenterService, DataCenterService>();
|
||||
services.AddSingleton<INavigationService, NavigationService>();
|
||||
services.AddSingleton<IDialogService, DialogService>();
|
||||
services.AddSingleton<INlogAppService, NlogAppService>();
|
||||
|
||||
// 注册MQTT服务管理器
|
||||
services.AddSingleton<IMqttServiceManager, MqttServiceManager>();
|
||||
@@ -248,6 +249,7 @@ public partial class App : System.Windows.Application
|
||||
services.AddSingleton<DevicesViewModel>();
|
||||
services.AddSingleton<DataTransformViewModel>();
|
||||
services.AddSingleton<SettingViewModel>();
|
||||
services.AddSingleton<LogHistoryViewModel>();
|
||||
services.AddTransient<VariableTableViewModel>(provider =>
|
||||
new VariableTableViewModel(
|
||||
provider.GetRequiredService<IMapper>(),
|
||||
@@ -270,6 +272,14 @@ public partial class App : System.Windows.Application
|
||||
provider.GetRequiredService<INotificationService>()
|
||||
)
|
||||
);
|
||||
services.AddSingleton<LogHistoryViewModel>(provider =>
|
||||
new LogHistoryViewModel(
|
||||
provider.GetRequiredService<IMapper>(),
|
||||
provider.GetRequiredService<INlogAppService>(),
|
||||
provider.GetRequiredService<IDialogService>(),
|
||||
provider.GetRequiredService<INotificationService>()
|
||||
)
|
||||
);
|
||||
services.AddScoped<MqttServerDetailViewModel>();
|
||||
|
||||
// 注册对话框视图模型
|
||||
@@ -292,6 +302,7 @@ public partial class App : System.Windows.Application
|
||||
services.AddSingleton<HomeView>();
|
||||
services.AddSingleton<DevicesView>();
|
||||
services.AddSingleton<VariableTableView>();
|
||||
services.AddSingleton<LogHistoryView>();
|
||||
services.AddScoped<DeviceDetailView>();
|
||||
services.AddScoped<MqttsView>();
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace DMS.WPF.Profiles
|
||||
CreateMap<VariableDto, VariableItemViewModel>().ReverseMap();
|
||||
CreateMap<VariableMqttAliasDto, VariableMqttAliasItemViewModel>().ReverseMap();
|
||||
CreateMap<VariableTableDto, VariableTableItemViewModel>().ReverseMap();
|
||||
CreateMap<NlogDto, NlogItemViewModel>().ReverseMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,15 @@ namespace DMS.WPF.Services;
|
||||
public class NavigationService : INavigationService
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly INotificationService _notificationService;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数。
|
||||
/// </summary>
|
||||
public NavigationService(IServiceProvider serviceProvider)
|
||||
public NavigationService(IServiceProvider serviceProvider,INotificationService notificationService)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_notificationService = notificationService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -34,8 +36,7 @@ public class NavigationService : INavigationService
|
||||
var viewModel = GetViewModelByKey(menu.TargetViewKey);
|
||||
if (viewModel == null)
|
||||
{
|
||||
var notificationService = App.Current.Services.GetRequiredService<INotificationService>();
|
||||
notificationService.ShowError($"切换界面失败,没有找到界面:{menu.TargetViewKey}");
|
||||
_notificationService.ShowError($"切换界面失败,没有找到界面:{menu.TargetViewKey}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,26 +52,36 @@ public class NavigationService : INavigationService
|
||||
|
||||
private ViewModelBase GetViewModelByKey(string key)
|
||||
{
|
||||
switch (key)
|
||||
try
|
||||
{
|
||||
case "HomeView":
|
||||
return App.Current.Services.GetRequiredService<HomeViewModel>();
|
||||
case "DevicesView":
|
||||
return App.Current.Services.GetRequiredService<DevicesViewModel>();
|
||||
case "DeviceDetailView":
|
||||
return App.Current.Services.GetRequiredService<DeviceDetailViewModel>();
|
||||
case "DataTransformView":
|
||||
return App.Current.Services.GetRequiredService<DataTransformViewModel>();
|
||||
case "VariableTableView":
|
||||
return App.Current.Services.GetRequiredService<VariableTableViewModel>();
|
||||
case "MqttsView":
|
||||
return App.Current.Services.GetRequiredService<MqttsViewModel>();
|
||||
case "MqttServerDetailView":
|
||||
return App.Current.Services.GetRequiredService<MqttServerDetailViewModel>();
|
||||
case "SettingView":
|
||||
return App.Current.Services.GetRequiredService<SettingViewModel>();
|
||||
default:
|
||||
return null;
|
||||
switch (key)
|
||||
{
|
||||
case "HomeView":
|
||||
return App.Current.Services.GetRequiredService<HomeViewModel>();
|
||||
case "DevicesView":
|
||||
return App.Current.Services.GetRequiredService<DevicesViewModel>();
|
||||
case "DeviceDetailView":
|
||||
return App.Current.Services.GetRequiredService<DeviceDetailViewModel>();
|
||||
case "DataTransformView":
|
||||
return App.Current.Services.GetRequiredService<DataTransformViewModel>();
|
||||
case "VariableTableView":
|
||||
return App.Current.Services.GetRequiredService<VariableTableViewModel>();
|
||||
case "LogHistoryView":
|
||||
return App.Current.Services.GetRequiredService<LogHistoryViewModel>();
|
||||
case "MqttsView":
|
||||
return App.Current.Services.GetRequiredService<MqttsViewModel>();
|
||||
case "MqttServerDetailView":
|
||||
return App.Current.Services.GetRequiredService<MqttServerDetailViewModel>();
|
||||
case "SettingView":
|
||||
return App.Current.Services.GetRequiredService<SettingViewModel>();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_notificationService.ShowError($"切换界面失败,获取:{key}对应的ViewModel时发生了错误:{e.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,24 @@
|
||||
// 文件: DMS.WPF/ViewModels/Items/NlogItemViewModel.cs
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using DMS.Core.Models;
|
||||
|
||||
namespace DMS.WPF.ViewModels.Items;
|
||||
|
||||
/// <summary>
|
||||
/// 代表日志列表中的单个日志项的ViewModel。
|
||||
/// 实现了INotifyPropertyChanged,其任何属性变化都会自动通知UI。
|
||||
/// </summary>
|
||||
public partial class NlogItemViewModel : ObservableObject
|
||||
public class NlogItemViewModel : ObservableObject
|
||||
{
|
||||
public int Id { get; set; }
|
||||
private Nlog _nlog;
|
||||
|
||||
[ObservableProperty]
|
||||
private DateTime _logTime;
|
||||
public NlogItemViewModel(Nlog nlog)
|
||||
{
|
||||
_nlog = nlog;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private string _level;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _threadId;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _threadName;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _callsite;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _callsiteLineNumber;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _message;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _logger;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _exception;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _callerFilePath;
|
||||
|
||||
[ObservableProperty]
|
||||
private int _callerLineNumber;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _callerMember;
|
||||
public int Id => _nlog.Id;
|
||||
public string Level => _nlog.Level;
|
||||
public string ThreadName => _nlog.ThreadName;
|
||||
public string Callsite => _nlog.Callsite;
|
||||
public string Message => _nlog.Message;
|
||||
public string Logger => _nlog.Logger;
|
||||
public string Exception => _nlog.Exception;
|
||||
public string StackTrace => _nlog.Exception; // Using Exception as StackTrace since it's not in the Nlog model
|
||||
public System.DateTime TimeStamp => _nlog.LogTime;
|
||||
}
|
||||
139
DMS.WPF/ViewModels/LogHistoryViewModel.cs
Normal file
139
DMS.WPF/ViewModels/LogHistoryViewModel.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using AutoMapper;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Core.Models;
|
||||
using DMS.WPF.Interfaces;
|
||||
using DMS.WPF.ViewModels.Items;
|
||||
using ObservableCollections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using DMS.WPF.ViewModels.Dialogs;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace DMS.WPF.ViewModels;
|
||||
|
||||
partial class LogHistoryViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
private readonly INlogAppService _nlogAppService;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly INotificationService _notificationService;
|
||||
|
||||
[ObservableProperty]
|
||||
private NlogItemViewModel _selectedLog;
|
||||
|
||||
[ObservableProperty]
|
||||
private IList _selectedLogs = new ArrayList();
|
||||
|
||||
[ObservableProperty]
|
||||
private string _searchText;
|
||||
|
||||
private readonly ObservableList<NlogItemViewModel> _logItemList;
|
||||
private readonly ISynchronizedView<NlogItemViewModel, NlogItemViewModel> _synchronizedView;
|
||||
public NotifyCollectionChangedSynchronizedViewList<NlogItemViewModel> LogItemListView { get; }
|
||||
|
||||
public LogHistoryViewModel(IMapper mapper, INlogAppService nlogAppService, IDialogService dialogService, INotificationService notificationService)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_nlogAppService = nlogAppService;
|
||||
_dialogService = dialogService;
|
||||
_notificationService = notificationService;
|
||||
|
||||
_logItemList = new ObservableList<NlogItemViewModel>();
|
||||
_synchronizedView = _logItemList.CreateView(v => v);
|
||||
LogItemListView = _synchronizedView.ToNotifyCollectionChanged();
|
||||
}
|
||||
|
||||
private bool FilterLogs(NlogItemViewModel item)
|
||||
{
|
||||
var searchTextLower = SearchText.ToLower();
|
||||
return item.Logger?.ToLower().Contains(searchTextLower) == true ||
|
||||
item.Message?.ToLower().Contains(searchTextLower) == true ||
|
||||
item.Exception?.ToLower().Contains(searchTextLower) == true ||
|
||||
item.StackTrace?.ToLower().Contains(searchTextLower) == true;
|
||||
}
|
||||
|
||||
partial void OnSearchTextChanged(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(SearchText))
|
||||
{
|
||||
_synchronizedView.ResetFilter();
|
||||
}
|
||||
else
|
||||
{
|
||||
_synchronizedView.AttachFilter(FilterLogs);
|
||||
}
|
||||
}
|
||||
|
||||
public override async void OnLoaded()
|
||||
{
|
||||
await LoadLogsAsync();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task RefreshLogsAsync()
|
||||
{
|
||||
await LoadLogsAsync();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task ClearLogsAsync()
|
||||
{
|
||||
var confirmDialogViewModel = new ConfirmDialogViewModel("确认", "确定要清空所有日志吗?", "确定");
|
||||
|
||||
var result = await _dialogService.ShowDialogAsync(confirmDialogViewModel);
|
||||
if (result == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _nlogAppService.ClearAllLogsAsync();
|
||||
_logItemList.Clear();
|
||||
_notificationService.ShowInfo("日志已清空");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_notificationService.ShowError($"清空日志时发生错误: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadLogsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var logs = await _nlogAppService.GetAllLogsAsync();
|
||||
var logItems = logs.Select(logDto =>
|
||||
{
|
||||
// Manually map NlogDto to Nlog
|
||||
var nlog = new Nlog
|
||||
{
|
||||
Id = logDto.Id,
|
||||
LogTime = logDto.LogTime,
|
||||
Level = logDto.Level,
|
||||
ThreadId = logDto.ThreadId,
|
||||
ThreadName = logDto.ThreadName,
|
||||
Callsite = logDto.Callsite,
|
||||
CallsiteLineNumber = logDto.CallsiteLineNumber,
|
||||
Message = logDto.Message,
|
||||
Logger = logDto.Logger,
|
||||
Exception = logDto.Exception,
|
||||
CallerFilePath = logDto.CallerFilePath,
|
||||
CallerLineNumber = logDto.CallerLineNumber,
|
||||
CallerMember = logDto.CallerMember
|
||||
};
|
||||
return new NlogItemViewModel(nlog);
|
||||
}).ToList();
|
||||
|
||||
_logItemList.Clear();
|
||||
_logItemList.AddRange(logItems);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
_notificationService.ShowError($"加载日志时发生错误: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
156
DMS.WPF/Views/LogHistoryView.xaml
Normal file
156
DMS.WPF/Views/LogHistoryView.xaml
Normal file
@@ -0,0 +1,156 @@
|
||||
<UserControl
|
||||
x:Class="DMS.WPF.Views.LogHistoryView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ex="clr-namespace:DMS.Extensions"
|
||||
xmlns:helper="clr-namespace:DMS.WPF.Helper"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:vm="clr-namespace:DMS.WPF.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:LogHistoryViewModel}"
|
||||
d:DesignHeight="600"
|
||||
d:DesignWidth="800"
|
||||
Loaded="LogHistoryView_OnLoaded"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<ex:BindingProxy x:Key="proxy" Data="{Binding}" />
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
|
||||
<!-- 标签字体的样式 -->
|
||||
<Style x:Key="LogHistoryLabelStyle" TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{DynamicResource SecondaryTextBrush}" />
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<!-- 值字体的样式 -->
|
||||
<Style x:Key="LogHistoryValueStyle" TargetType="TextBlock">
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="MinWidth" Value="100" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<ikw:SimpleStackPanel Margin="10" DockPanel.Dock="Top">
|
||||
<!-- 操作菜单 -->
|
||||
<controls:CommandBar
|
||||
x:Name="PrimaryCommandBar"
|
||||
DefaultLabelPosition="Right"
|
||||
IsOpen="False">
|
||||
<ui:AppBarButton Command="{Binding RefreshLogsCommand}" Label="刷新日志">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Refresh}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
|
||||
<ui:AppBarButton Command="{Binding ClearLogsCommand}" Label="清空日志">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Delete}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
|
||||
<ui:AppBarButton x:Name="ShareButton" Label="Share">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Share}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
<ui:CommandBar.SecondaryCommands>
|
||||
<ui:AppBarButton
|
||||
x:Name="SettingsButton"
|
||||
Icon="Setting"
|
||||
Label="Settings" />
|
||||
</ui:CommandBar.SecondaryCommands>
|
||||
|
||||
</controls:CommandBar>
|
||||
<!-- 日志的搜索信息 -->
|
||||
<ikw:SimpleStackPanel
|
||||
Margin="5"
|
||||
Orientation="Horizontal"
|
||||
Spacing="10">
|
||||
<TextBlock Style="{StaticResource LogHistoryLabelStyle}" Text="搜索:" />
|
||||
<TextBox
|
||||
Width="200"
|
||||
Margin="5,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
ui:ControlHelper.PlaceholderText="搜索日志..."
|
||||
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</ikw:SimpleStackPanel>
|
||||
|
||||
|
||||
</ikw:SimpleStackPanel>
|
||||
|
||||
<DataGrid
|
||||
x:Name="BasicGridView"
|
||||
Margin="10"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserDeleteRows="False"
|
||||
CanUserSortColumns="False"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding LogItemListView}"
|
||||
SelectedItem="{Binding SelectedLog}"
|
||||
SelectionMode="Extended"
|
||||
Style="{StaticResource DataGridBaseStyle}">
|
||||
<i:Interaction.Behaviors>
|
||||
<helper:SelectedItemsBehavior SelectedItems="{Binding SelectedLogs}" />
|
||||
</i:Interaction.Behaviors>
|
||||
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Command="{Binding RefreshLogsCommand}" Header="刷新日志">
|
||||
<MenuItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Refresh}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Command="{Binding ClearLogsCommand}" Header="清空日志">
|
||||
<MenuItem.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Delete}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<!-- <Setter Property="Background" Value="#fff"/> -->
|
||||
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Level}" Value="Error">
|
||||
<Setter Property="Background" Value="LightCoral" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Level}" Value="Warn">
|
||||
<Setter Property="Background" Value="LightGoldenrodYellow" />
|
||||
<Setter Property="Foreground" Value="Black" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
</DataTrigger>
|
||||
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource HoverBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding TimeStamp, StringFormat='{}{0:yyyy-MM-dd HH:mm:ss}'}" Header="时间戳" />
|
||||
<DataGridTextColumn Binding="{Binding Level}" Header="级别" />
|
||||
<DataGridTextColumn Binding="{Binding Logger}" Header="记录器" />
|
||||
<DataGridTextColumn Binding="{Binding Message}" Header="消息" />
|
||||
<DataGridTextColumn Binding="{Binding Exception}" Header="异常" />
|
||||
<DataGridTextColumn Binding="{Binding StackTrace}" Header="堆栈跟踪" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
24
DMS.WPF/Views/LogHistoryView.xaml.cs
Normal file
24
DMS.WPF/Views/LogHistoryView.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using DMS.WPF.ViewModels;
|
||||
|
||||
namespace DMS.WPF.Views;
|
||||
|
||||
/// <summary>
|
||||
/// LogHistoryView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LogHistoryView : UserControl
|
||||
{
|
||||
public LogHistoryView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void LogHistoryView_OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is LogHistoryViewModel viewModel)
|
||||
{
|
||||
viewModel.OnLoaded();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,10 @@
|
||||
<DataTemplate DataType="{x:Type vm:SettingViewModel}">
|
||||
<local:SettingView />
|
||||
</DataTemplate>
|
||||
<!-- 日志历史页 -->
|
||||
<DataTemplate DataType="{x:Type vm:LogHistoryViewModel}">
|
||||
<local:LogHistoryView />
|
||||
</DataTemplate>
|
||||
<!-- 设备详情页 -->
|
||||
<DataTemplate DataType="{x:Type vm:DeviceDetailViewModel}">
|
||||
<local:DeviceDetailView />
|
||||
|
||||
Reference in New Issue
Block a user