using System.Collections.Specialized; using System.ComponentModel; using System.Windows; using XP.Common.Logging.Interfaces; using XP.Hardware.Plc.Abstractions; using XP.Hardware.PLC.ViewModels; namespace XP.Hardware.PLC.Views { /// /// PLC 测试工具窗口 Code-Behind | PLC Test Bench Window Code-Behind /// public partial class PlcTestBenchWindow : Window { private readonly PlcTestBenchViewModel _viewModel; /// /// 构造函数 | Constructor /// /// PLC 客户端接口 | PLC client interface /// 日志服务 | Logger service public PlcTestBenchWindow(IPlcClient plcClient, ILoggerService logger) { InitializeComponent(); _viewModel = new PlcTestBenchViewModel(plcClient, logger); DataContext = _viewModel; // 继承主窗口图标 if (Application.Current?.MainWindow != null) { Icon = Application.Current.MainWindow.Icon; } // 订阅日志集合变化,自动滚动到最新条目 | Subscribe to log collection changes for auto-scroll _viewModel.LogEntries.CollectionChanged += LogEntries_CollectionChanged; } /// /// 日志集合变化时自动滚动到最新条目 | Auto-scroll to latest entry on collection change /// private void LogEntries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add && _viewModel.LogEntries.Count > 0) { // 使用 Dispatcher 延迟执行,确保 UI 渲染完成后再滚动 | Use Dispatcher to ensure UI rendering is complete before scrolling Dispatcher.InvokeAsync(() => { LogListBox.ScrollIntoView(_viewModel.LogEntries[_viewModel.LogEntries.Count - 1]); }, System.Windows.Threading.DispatcherPriority.Background); } } /// /// 窗口关闭时释放资源 | Release resources on window closing /// protected override void OnClosing(CancelEventArgs e) { _viewModel?.Cleanup(); base.OnClosing(e); } } }