using DeviceService.Core; using DeviceService.Device; using DeviceService.Driver; using DeviceService.Logging; using DeviceService.Service; using System.Collections.ObjectModel; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Threading; namespace DeviceService; /// /// 设备树分组节点(按 IDevice.Type 分组)。 /// public class DeviceGroupNode { public DeviceGroupNode(string type, IEnumerable children) { Type = type; Children = new ObservableCollection(children); } public string Type { get; } public ObservableCollection Children { get; } } /// /// 设备树叶子节点。 /// public class DeviceNode { public DeviceNode(IDevice device) { Device = device; } public IDevice Device { get; } public string DisplayName => $"{Device.DeviceId}({Device.Brand})"; } /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private readonly DriverManager _manager = DriverManager.Instance; private readonly ObservableCollection _groups = new ObservableCollection(); public MainWindow() { InitializeComponent(); DeviceTree.ItemsSource = _groups; Loaded += MainWindow_Loaded; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { // 加载驱动包,供设备 Init 时查找驱动 _manager.Scan(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Driver"), s => { }); // 扫描 DeviceDesc 注解,填充 AllDeviceType DeviceHelper.ScanDeviceTypes(); // 以数据库为准恢复设备列表(不调用 Init,避免启动即占用硬件) ReloadDeviceList(); RefreshDeviceTree(); } private void RefreshButton_Click(object sender, RoutedEventArgs e) { RefreshDeviceTree(); } private void AddDeviceButton_Click(object sender, RoutedEventArgs e) { var dialog = new AddDeviceWindow { Owner = this }; if (dialog.ShowDialog() != true || dialog.Device == null) { return; } IDevice device = dialog.Device; if (!DeviceHelper.SaveDevice(device)) { HeaderText.Text = $"设备 {device.DeviceId} 保存失败"; return; } // 保存成功后从数据库重新读取设备列表,而不是把弹窗里新建的实例直接塞进列表 ReloadDeviceList(); RefreshDeviceTree(); HeaderText.Text = $"已添加设备 {device.DeviceId}"; } /// 以 Config\Devices.db 为准刷新内存中的设备列表(不调用 Init)。 private static void ReloadDeviceList() { DeviceManager.Refresh(DeviceHelper.LoadDevices()); } private void StartService_Click(object sender, RoutedEventArgs e) { // 运行中点击即为“停止” if (ServiceStateMachine.GlobalState.State == ServiceStatus.Running) { ServiceManager.Stop(); HeaderText.Text = "服务已停止"; return; } try { ServiceManager.Start(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void DebugWindowButton_Click(object sender, RoutedEventArgs e) { var debug = new DebugWindow { Owner = this }; debug.Show(); } private void LogWindowButton_Click(object sender, RoutedEventArgs e) { var log = new LogWindow { Owner = this }; log.Show(); } private void DeviceTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) { if (e.NewValue is DeviceNode node) { ShowDeviceConfig(node.Device); } else { ConfigHost.Content = null; HeaderText.Text = "设备配置"; } } private void ShowDeviceConfig(IDevice device) { HeaderText.Text = $"{device.Type} - {device.DeviceId}"; UserControl? control = DeviceConfigControlFactory.Create(device); if (control == null) { // 未按命名规则找到对应配置控件 ConfigHost.Content = new TextBlock { Text = $"未找到 {device.GetType().Name}ConfigControl,无法显示该设备的配置界面。", Margin = new Thickness(8), TextWrapping = TextWrapping.Wrap, TextAlignment = TextAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; return; } control.DataContext = device; ConfigHost.Content = control; } private void RefreshDeviceTree() { string? selectedId = (DeviceTree.SelectedItem as DeviceNode)?.Device.DeviceId; _groups.Clear(); foreach (var group in DeviceManager.Devices .GroupBy(d => d.Type) .OrderBy(g => g.Key, StringComparer.Ordinal)) { _groups.Add(new DeviceGroupNode(group.Key, group.Select(d => new DeviceNode(d)))); } // 容器在本次布局之后才生成,延后展开,确保新增节点能显示出来 Dispatcher.BeginInvoke(new Action(ExpandAllGroups), DispatcherPriority.Loaded); } /// 展开所有分组节点。 private void ExpandAllGroups() { if (DeviceTree.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) { EventHandler? handler = null; handler = (s, e) => { if (DeviceTree.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) { DeviceTree.ItemContainerGenerator.StatusChanged -= handler; ExpandAllGroups(); } }; DeviceTree.ItemContainerGenerator.StatusChanged += handler; return; } for (int i = 0; i < DeviceTree.Items.Count; i++) { if (DeviceTree.ItemContainerGenerator.ContainerFromIndex(i) is TreeViewItem item) { item.IsExpanded = true; } } } }