Newer
Older
Correlator / Correlator / ViewModels / AudioFileDialogViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Correlator.Model;
using Correlator.Util;
using HandyControl.Data;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using MessageBox = System.Windows.MessageBox;

namespace Correlator.ViewModels
{
    public class AudioFileDialogViewModel : BindableBase, IDialogAware
    {
        #region 属性绑定

        public string Title => "音频文件列表";

        public event Action<IDialogResult> RequestClose
        {
            add { }
            remove { }
        }

        private ObservableCollection<AudioFile> _audioFiles;

        public ObservableCollection<AudioFile> AudioFiles
        {
            get => _audioFiles;
            set
            {
                _audioFiles = value;
                RaisePropertyChanged();
            }
        }

        private int _maxPage;

        public int MaxPage
        {
            get => _maxPage;
            set
            {
                _maxPage = value;
                RaisePropertyChanged();
            }
        }

        private bool _taskHasCompleted;

        public bool TaskHasCompleted
        {
            get => _taskHasCompleted;
            set
            {
                _taskHasCompleted = value;
                RaisePropertyChanged();
            }
        }

        #endregion

        #region DelegateCommand

        public DelegateCommand<AudioFile> PlayAudioCommand { get; set; }
        public DelegateCommand<FunctionEventArgs<int>> PageUpdatedCmd { get; set; }

        #endregion

        private readonly IDialogService _dialogService;
        private List<AudioFile> _totalFiles;

        /// <summary>
        /// 列表每页条目数
        /// </summary>
        private const int PerPageItemCount = 8;

        public AudioFileDialogViewModel(IDialogService dialogService)
        {
            _dialogService = dialogService;

            PlayAudioCommand = new DelegateCommand<AudioFile>(PlayAudio);
            PageUpdatedCmd = new DelegateCommand<FunctionEventArgs<int>>(PageUpdated);
        }

        private void PlayAudio(object audioFile)
        {
            if (audioFile == null)
            {
                MessageBox.Show("音频文件路径错误,无法播放", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            _dialogService.ShowDialog("AudioVisualizeDialog", new DialogParameters
            {
                { "AudioFile", audioFile }
            }, delegate { });
        }

        private void PageUpdated(FunctionEventArgs<int> args)
        {
            var audioFiles = _totalFiles
                .Skip((args.Info - 1) * PerPageItemCount)
                .Take(PerPageItemCount)
                .ToList();
            AudioFiles = audioFiles.ToObservableCollection();
        }

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {
        }

        public async void OnDialogOpened(IDialogParameters parameters)
        {
            _totalFiles = await GetTotalAudioFilesAsync();
            MaxPage = (_totalFiles.Count + PerPageItemCount - 1) / PerPageItemCount;
            AudioFiles = _totalFiles.Take(PerPageItemCount).ToList().ToObservableCollection();
        }

        /// <summary>
        /// 异步遍历文件夹,防止卡主线程
        /// </summary>
        /// <returns></returns>
        private async Task<List<AudioFile>> GetTotalAudioFilesAsync()
        {
            var audioFiles = new List<AudioFile>();

            await Task.Run(() => TraverseFolder(DirectoryManager.GetAudioDir(), audioFiles));
            TaskHasCompleted = true;
            return audioFiles.OrderBy(file => file.CreationTime).Reverse().ToList();
        }

        /// <summary>
        /// 遍历文件夹并生成相应的数据类型集合
        /// </summary>
        /// <param name="folderPath"></param>
        /// <param name="audioFiles"></param>
        private static void TraverseFolder(string folderPath, List<AudioFile> audioFiles)
        {
            var files = new DirectoryInfo(folderPath).GetFiles()
                .OrderBy(file => file.CreationTime)
                .Reverse();
            foreach (var file in files)
            {
                var fileName = file.Name;
                if (fileName.Contains("听音") && file.Length < 1024 * 50)
                {
                    //筛选小于50K的音频文件
                    RuntimeCache.SmallAudioFiles.Add(file.FullName);
                }
                else
                {
                    audioFiles.Add(new AudioFile
                    {
                        FileName = fileName,
                        FullPath = file.FullName,
                        FileSize = file.Length.FormatFileSize(),
                        Duration = file.FullName.GetAudioDuration(),
                        CreationTime = file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")
                    });
                }
            }
        }
    }
}