using SHH.Contracts; using System.IO; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; namespace SHH.CameraDashboard { public class VideoTileViewModel : ViewModelBase, IDisposable { // --- 绑定属性 --- private ImageSource _displayImage; public ImageSource DisplayImage { get => _displayImage; set => SetProperty(ref _displayImage, value); } private string _cameraName; public string CameraName { get => _cameraName; set => SetProperty(ref _cameraName, value); } private string _statusInfo; public string StatusInfo { get => _statusInfo; set => SetProperty(ref _statusInfo, value); } private bool _isConnected; public bool IsConnected { get => _isConnected; set => SetProperty(ref _isConnected, value); } // --- 构造函数 --- public VideoTileViewModel(string ip, int port, string name) { CameraName = name; StatusInfo = "连接中..."; IsConnected = true; } private void HandleNewFrame(VideoPayload payload) { // 必须回到 UI 线程更新 ImageSource Application.Current.Dispatcher.Invoke(() => { // 1. 更新图片 byte[] data = payload.TargetImageBytes ?? payload.OriginalImageBytes; if (data != null && data.Length > 0) { DisplayImage = ByteToBitmap(data); } // 2. 更新状态文字 StatusInfo = $"{payload.CaptureTime:HH:mm:ss} | {data?.Length / 1024} KB"; }); } // 简单的 Bytes 转 BitmapImage (生产环境建议优化为 WriteableBitmap) private BitmapImage ByteToBitmap(byte[] bytes) { var bitmap = new BitmapImage(); using (var stream = new MemoryStream(bytes)) { bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.StreamSource = stream; bitmap.EndInit(); } bitmap.Freeze(); // 必须冻结才能跨线程 return bitmap; } public void Dispose() { IsConnected = false; } } }