diff --git a/DownKyi/App.xaml.cs b/DownKyi/App.xaml.cs index 1de062f..ff95d7b 100644 --- a/DownKyi/App.xaml.cs +++ b/DownKyi/App.xaml.cs @@ -159,15 +159,17 @@ namespace DownKyi containerRegistry.RegisterForNavigation(ViewLoginViewModel.Tag); containerRegistry.RegisterForNavigation(ViewVideoDetailViewModel.Tag); containerRegistry.RegisterForNavigation(ViewSettingsViewModel.Tag); - containerRegistry.RegisterForNavigation(ViewDownloadManagerViewModel.Tag); containerRegistry.RegisterForNavigation(ViewToolboxViewModel.Tag); - containerRegistry.RegisterForNavigation(ViewUserSpaceViewModel.Tag); - containerRegistry.RegisterForNavigation(ViewMySpaceViewModel.Tag); + containerRegistry.RegisterForNavigation(ViewDownloadManagerViewModel.Tag); containerRegistry.RegisterForNavigation(ViewPublicFavoritesViewModel.Tag); + + containerRegistry.RegisterForNavigation(ViewUserSpaceViewModel.Tag); containerRegistry.RegisterForNavigation(ViewPublicationViewModel.Tag); containerRegistry.RegisterForNavigation(ViewModels.ViewChannelViewModel.Tag); + containerRegistry.RegisterForNavigation(ViewMySpaceViewModel.Tag); containerRegistry.RegisterForNavigation(ViewMyFavoritesViewModel.Tag); + containerRegistry.RegisterForNavigation(ViewMyBangumiFollowViewModel.Tag); // downloadManager pages containerRegistry.RegisterForNavigation(ViewDownloadingViewModel.Tag); diff --git a/DownKyi/CustomControl/CustomPagerViewModel.cs b/DownKyi/CustomControl/CustomPagerViewModel.cs index 07034fb..5a6ed4c 100644 --- a/DownKyi/CustomControl/CustomPagerViewModel.cs +++ b/DownKyi/CustomControl/CustomPagerViewModel.cs @@ -74,6 +74,8 @@ namespace DownKyi.CustomControl OnCountChanged(count); + SetView(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count")); } } @@ -100,6 +102,8 @@ namespace DownKyi.CustomControl { current = value; + SetView(); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Current")); } } diff --git a/DownKyi/DownKyi.csproj b/DownKyi/DownKyi.csproj index 10b62ac..7013f51 100644 --- a/DownKyi/DownKyi.csproj +++ b/DownKyi/DownKyi.csproj @@ -100,6 +100,7 @@ + @@ -152,6 +153,7 @@ + @@ -218,6 +220,9 @@ ViewLogin.xaml + + ViewMyBangumiFollow.xaml + ViewMyFavorites.xaml @@ -402,6 +407,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/DownKyi/Languages/Default.xaml b/DownKyi/Languages/Default.xaml index d97fdc1..4eadb50 100644 --- a/DownKyi/Languages/Default.xaml +++ b/DownKyi/Languages/Default.xaml @@ -76,6 +76,9 @@ 投稿: 收藏于: + + 我的订阅 + 下载选中项 下载全部 diff --git a/DownKyi/ViewModels/PageViewModels/BangumiFollowMedia.cs b/DownKyi/ViewModels/PageViewModels/BangumiFollowMedia.cs new file mode 100644 index 0000000..60bbf15 --- /dev/null +++ b/DownKyi/ViewModels/PageViewModels/BangumiFollowMedia.cs @@ -0,0 +1,121 @@ +using DownKyi.Core.BiliApi.BiliUtils; +using DownKyi.Utils; +using Prism.Commands; +using Prism.Events; +using Prism.Mvvm; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels.PageViewModels +{ + public class BangumiFollowMedia : BindableBase + { + protected readonly IEventAggregator eventAggregator; + + public BangumiFollowMedia(IEventAggregator eventAggregator) + { + this.eventAggregator = eventAggregator; + } + + // media id + public long MediaId { get; set; } + + // season id + public long SeasonId { get; set; } + + #region 页面属性申明 + + // 是否选中 + private bool isSelected; + public bool IsSelected + { + get => isSelected; + set => SetProperty(ref isSelected, value); + } + + // 封面 + private BitmapImage cover; + public BitmapImage Cover + { + get => cover; + set => SetProperty(ref cover, value); + } + + // 视频标题 + private string title; + public string Title + { + get => title; + set => SetProperty(ref title, value); + } + + // 视频类型名称 + private string seasonTypeName; + public string SeasonTypeName + { + get => seasonTypeName; + set => SetProperty(ref seasonTypeName, value); + } + + // 地区 + private string area; + public string Area + { + get => area; + set => SetProperty(ref area, value); + } + + // 标记是否会员 + private string badge; + public string Badge + { + get => badge; + set => SetProperty(ref badge, value); + } + + // 简介 + private string evaluate; + public string Evaluate + { + get => evaluate; + set => SetProperty(ref evaluate, value); + } + + // 视频更新进度 + private string indexShow; + public string IndexShow + { + get => indexShow; + set => SetProperty(ref indexShow, value); + } + + // 观看进度 + private string progress; + public string Progress + { + get => progress; + set => SetProperty(ref progress, value); + } + + #endregion + + #region 命令申明 + + // 视频标题点击事件 + private DelegateCommand titleCommand; + public DelegateCommand TitleCommand => titleCommand ?? (titleCommand = new DelegateCommand(ExecuteTitleCommand)); + + /// + /// 视频标题点击事件 + /// + /// + private void ExecuteTitleCommand(object parameter) + { + if (!(parameter is string tag)) { return; } + + NavigateToView.NavigationView(eventAggregator, ViewVideoDetailViewModel.Tag, tag, $"{ParseEntrance.BangumiMediaUrl}md{MediaId}"); + } + + #endregion + + } +} diff --git a/DownKyi/ViewModels/PageViewModels/ChannelMedia.cs b/DownKyi/ViewModels/PageViewModels/ChannelMedia.cs index 6bcf0ea..5fd54ff 100644 --- a/DownKyi/ViewModels/PageViewModels/ChannelMedia.cs +++ b/DownKyi/ViewModels/PageViewModels/ChannelMedia.cs @@ -19,6 +19,8 @@ namespace DownKyi.ViewModels.PageViewModels public long Avid { get; set; } public string Bvid { get; set; } + #region 页面属性申明 + private bool isSelected; public bool IsSelected { @@ -61,6 +63,10 @@ namespace DownKyi.ViewModels.PageViewModels set => SetProperty(ref createTime, value); } + #endregion + + #region 命令申明 + // 视频标题点击事件 private DelegateCommand titleCommand; public DelegateCommand TitleCommand => titleCommand ?? (titleCommand = new DelegateCommand(ExecuteTitleCommand)); @@ -78,5 +84,7 @@ namespace DownKyi.ViewModels.PageViewModels //System.Diagnostics.Process.Start(url); } + #endregion + } } diff --git a/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs b/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs index 6d78abb..ad6fdcf 100644 --- a/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs +++ b/DownKyi/ViewModels/PageViewModels/PublicationMedia.cs @@ -19,6 +19,8 @@ namespace DownKyi.ViewModels.PageViewModels public long Avid { get; set; } public string Bvid { get; set; } + #region 页面属性申明 + private bool isSelected; public bool IsSelected { @@ -61,6 +63,10 @@ namespace DownKyi.ViewModels.PageViewModels set => SetProperty(ref createTime, value); } + #endregion + + #region 命令申明 + // 视频标题点击事件 private DelegateCommand titleCommand; public DelegateCommand TitleCommand => titleCommand ?? (titleCommand = new DelegateCommand(ExecuteTitleCommand)); @@ -78,5 +84,7 @@ namespace DownKyi.ViewModels.PageViewModels //System.Diagnostics.Process.Start(url); } + #endregion + } } diff --git a/DownKyi/ViewModels/ViewChannelViewModel.cs b/DownKyi/ViewModels/ViewChannelViewModel.cs index bea825d..ae5d324 100644 --- a/DownKyi/ViewModels/ViewChannelViewModel.cs +++ b/DownKyi/ViewModels/ViewChannelViewModel.cs @@ -16,6 +16,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -246,8 +247,12 @@ namespace DownKyi.ViewModels int i = 0; await Task.Run(() => { + // 为了避免执行其他操作时, + // Medias变化导致的异常 + var list = Medias.ToList(); + // 添加到下载 - foreach (var media in Medias) + foreach (var media in list) { // 只下载选中项,跳过未选中项 if (isOnlySelected && !media.IsSelected) { continue; } diff --git a/DownKyi/ViewModels/ViewMyBangumiFollowViewModel.cs b/DownKyi/ViewModels/ViewMyBangumiFollowViewModel.cs new file mode 100644 index 0000000..36e50e4 --- /dev/null +++ b/DownKyi/ViewModels/ViewMyBangumiFollowViewModel.cs @@ -0,0 +1,504 @@ +using DownKyi.Core.BiliApi.BiliUtils; +using DownKyi.Core.BiliApi.VideoStream; +using DownKyi.Core.Storage; +using DownKyi.CustomControl; +using DownKyi.Events; +using DownKyi.Images; +using DownKyi.Services; +using DownKyi.Services.Download; +using DownKyi.Utils; +using DownKyi.ViewModels.PageViewModels; +using Prism.Commands; +using Prism.Events; +using Prism.Regions; +using Prism.Services.Dialogs; +using System; +using System.Collections; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Imaging; + +namespace DownKyi.ViewModels +{ + public class ViewMyBangumiFollowViewModel : BaseViewModel + { + public const string Tag = "PageMyBangumiFollow"; + + private readonly IDialogService dialogService; + + private CancellationTokenSource tokenSource; + + private long mid = -1; + + // 每页视频数量,暂时在此写死,以后在设置中增加选项 + private readonly int VideoNumberInPage = 15; + + #region 页面属性申明 + + private string pageName = Tag; + public string PageName + { + get => pageName; + set => SetProperty(ref pageName, value); + } + + private VectorImage arrowBack; + public VectorImage ArrowBack + { + get => arrowBack; + set => SetProperty(ref arrowBack, value); + } + + private ObservableCollection tabHeaders; + public ObservableCollection TabHeaders + { + get => tabHeaders; + set => SetProperty(ref tabHeaders, value); + } + + private int selectTabId; + public int SelectTabId + { + get => selectTabId; + set => SetProperty(ref selectTabId, value); + } + + private bool isEnabled = true; + public bool IsEnabled + { + get => isEnabled; + set => SetProperty(ref isEnabled, value); + } + + private Visibility contentVisibility; + public Visibility ContentVisibility + { + get => contentVisibility; + set => SetProperty(ref contentVisibility, value); + } + + private CustomPagerViewModel pager; + public CustomPagerViewModel Pager + { + get => pager; + set => SetProperty(ref pager, value); + } + + private ObservableCollection medias; + public ObservableCollection Medias + { + get => medias; + set => SetProperty(ref medias, value); + } + + private bool isSelectAll; + public bool IsSelectAll + { + get => isSelectAll; + set => SetProperty(ref isSelectAll, value); + } + + private GifImage loading; + public GifImage Loading + { + get => loading; + set => SetProperty(ref loading, value); + } + + private Visibility loadingVisibility; + public Visibility LoadingVisibility + { + get => loadingVisibility; + set => SetProperty(ref loadingVisibility, value); + } + + private Visibility noDataVisibility; + public Visibility NoDataVisibility + { + get => noDataVisibility; + set => SetProperty(ref noDataVisibility, value); + } + + #endregion + + public ViewMyBangumiFollowViewModel(IEventAggregator eventAggregator, IDialogService dialogService) : base(eventAggregator) + { + this.dialogService = dialogService; + + #region 属性初始化 + + // 初始化loading gif + Loading = new GifImage(Properties.Resources.loading); + Loading.StartAnimate(); + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Collapsed; + + ArrowBack = NavigationIcon.Instance().ArrowBack; + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + + TabHeaders = new ObservableCollection + { + new TabHeader { Id = (int)Core.BiliApi.Users.Models.BangumiType.ANIME, Title = "追番" }, + new TabHeader { Id = (int)Core.BiliApi.Users.Models.BangumiType.EPISODE, Title = "追剧" } + }; + + Medias = new ObservableCollection(); + + #endregion + + } + + #region 命令申明 + + // 返回事件 + private DelegateCommand backSpaceCommand; + public DelegateCommand BackSpaceCommand => backSpaceCommand ?? (backSpaceCommand = new DelegateCommand(ExecuteBackSpace)); + + /// + /// 返回事件 + /// + private void ExecuteBackSpace() + { + InitView(); + + ArrowBack.Fill = DictionaryResource.GetColor("ColorText"); + + // 结束任务 + tokenSource?.Cancel(); + + NavigationParam parameter = new NavigationParam + { + ViewName = ParentView, + ParentViewName = null, + Parameter = null + }; + eventAggregator.GetEvent().Publish(parameter); + } + + // 顶部tab点击事件 + private DelegateCommand tabHeadersCommand; + public DelegateCommand TabHeadersCommand => tabHeadersCommand ?? (tabHeadersCommand = new DelegateCommand(ExecuteTabHeadersCommand, CanExecuteTabHeadersCommand)); + + /// + /// 左侧tab点击事件 + /// + /// + private void ExecuteTabHeadersCommand(object parameter) + { + if (!(parameter is TabHeader tabHeader)) { return; } + + // 页面选择 + Pager = new CustomPagerViewModel(1, 1); + Pager.CurrentChanged += OnCurrentChanged_Pager; + Pager.CountChanged += OnCountChanged_Pager; + Pager.Current = 1; + } + + /// + /// 顶部tab点击事件是否允许执行 + /// + /// + /// + private bool CanExecuteTabHeadersCommand(object parameter) + { + return IsEnabled; + } + + // 全选按钮点击事件 + private DelegateCommand selectAllCommand; + public DelegateCommand SelectAllCommand => selectAllCommand ?? (selectAllCommand = new DelegateCommand(ExecuteSelectAllCommand)); + + /// + /// 全选按钮点击事件 + /// + /// + private void ExecuteSelectAllCommand(object parameter) + { + if (IsSelectAll) + { + foreach (var item in Medias) + { + item.IsSelected = true; + } + } + else + { + foreach (var item in Medias) + { + item.IsSelected = false; + } + } + } + + // 列表选择事件 + private DelegateCommand mediasCommand; + public DelegateCommand MediasCommand => mediasCommand ?? (mediasCommand = new DelegateCommand(ExecuteMediasCommand)); + + /// + /// 列表选择事件 + /// + /// + private void ExecuteMediasCommand(object parameter) + { + if (!(parameter is IList selectedMedia)) { return; } + + if (selectedMedia.Count == Medias.Count) + { + IsSelectAll = true; + } + else + { + IsSelectAll = false; + } + } + + // 添加选中项到下载列表事件 + private DelegateCommand addToDownloadCommand; + public DelegateCommand AddToDownloadCommand => addToDownloadCommand ?? (addToDownloadCommand = new DelegateCommand(ExecuteAddToDownloadCommand)); + + /// + /// 添加选中项到下载列表事件 + /// + private void ExecuteAddToDownloadCommand() + { + AddToDownload(true); + } + + // 添加所有视频到下载列表事件 + private DelegateCommand addAllToDownloadCommand; + public DelegateCommand AddAllToDownloadCommand => addAllToDownloadCommand ?? (addAllToDownloadCommand = new DelegateCommand(ExecuteAddAllToDownloadCommand)); + + /// + /// 添加所有视频到下载列表事件 + /// + private void ExecuteAddAllToDownloadCommand() + { + AddToDownload(false); + } + + #endregion + + /// + /// 添加到下载 + /// + /// + private async void AddToDownload(bool isOnlySelected) + { + // 订阅里只有BANGUMI类型 + AddToDownloadService addToDownloadService = new AddToDownloadService(PlayStreamType.BANGUMI); + + // 选择文件夹 + string directory = addToDownloadService.SetDirectory(dialogService); + + // 视频计数 + int i = 0; + await Task.Run(() => + { + // 为了避免执行其他操作时, + // Medias变化导致的异常 + var list = Medias.ToList(); + + // 添加到下载 + foreach (var media in list) + { + // 只下载选中项,跳过未选中项 + if (isOnlySelected && !media.IsSelected) { continue; } + + /// 有分P的就下载全部 + + // 开启服务 + BangumiInfoService service = new BangumiInfoService($"{ParseEntrance.BangumiMediaUrl}md{media.MediaId}"); + + addToDownloadService.SetVideoInfoService(service); + addToDownloadService.GetVideo(); + addToDownloadService.ParseVideo(service); + // 下载 + i += addToDownloadService.AddToDownload(eventAggregator, directory); + } + }); + + if (directory == null) + { + return; + } + + // 通知用户添加到下载列表的结果 + if (i == 0) + { + eventAggregator.GetEvent().Publish(DictionaryResource.GetString("TipAddDownloadingZero")); + } + else + { + eventAggregator.GetEvent().Publish($"{DictionaryResource.GetString("TipAddDownloadingFinished1")}{i}{DictionaryResource.GetString("TipAddDownloadingFinished2")}"); + } + } + + private void OnCountChanged_Pager(int count) { } + + private bool OnCurrentChanged_Pager(int old, int current) + { + if (!IsEnabled) + { + //Pager.Current = old; + return false; + } + + UpdateBangumiMediaList(current); + + return true; + } + + private async void UpdateBangumiMediaList(int current) + { + Medias.Clear(); + LoadingVisibility = Visibility.Visible; + NoDataVisibility = Visibility.Collapsed; + + // 是否正在获取数据 + // 在所有的退出分支中都需要设为true + IsEnabled = false; + + var tab = TabHeaders[SelectTabId]; + Core.BiliApi.Users.Models.BangumiType type = (Core.BiliApi.Users.Models.BangumiType)tab.Id; + + await Task.Run(() => + { + CancellationToken cancellationToken = tokenSource.Token; + + var bangumiFollows = Core.BiliApi.Users.UserSpace.GetBangumiFollow(mid, type, current, VideoNumberInPage); + if (bangumiFollows == null || bangumiFollows.List == null || bangumiFollows.List.Count == 0) + { + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Visible; + return; + } + + // 更新总页码 + Pager.Count = (int)Math.Ceiling((double)bangumiFollows.Total / VideoNumberInPage); + // 更新内容 + ContentVisibility = Visibility.Visible; + + foreach (var bangumiFollow in bangumiFollows.List) + { + // 查询、保存封面 + string coverUrl = bangumiFollow.Cover; + BitmapImage cover; + if (coverUrl == null || coverUrl == "") + { + cover = null; + } + else + { + if (!coverUrl.ToLower().StartsWith("http")) + { + coverUrl = $"https:{bangumiFollow.Cover}"; + } + + StorageCover storageCover = new StorageCover(); + cover = storageCover.GetCoverThumbnail(bangumiFollow.MediaId, bangumiFollow.SeasonId.ToString(), -1, coverUrl, 110, 140); + } + + // 地区 + string area = string.Empty; + if (bangumiFollow.Areas != null && bangumiFollow.Areas.Count > 0) + { + area = bangumiFollow.Areas[0].Name; + } + + // 视频更新进度 + string indexShow = string.Empty; + if (bangumiFollow.NewEp != null) + { + indexShow = bangumiFollow.NewEp.IndexShow; + } + + // 观看进度 + string progress; + if (bangumiFollow.Progress == null || bangumiFollow.Progress == "") + { + progress = "尚未观看"; + } + else + { + progress = bangumiFollow.Progress; + } + + App.PropertyChangeAsync(() => + { + BangumiFollowMedia media = new BangumiFollowMedia(eventAggregator) + { + MediaId = bangumiFollow.MediaId, + SeasonId = bangumiFollow.SeasonId, + Title = bangumiFollow.Title, + SeasonTypeName = bangumiFollow.SeasonTypeName, + Area = area, + Badge = bangumiFollow.Badge, + Cover = cover ?? new BitmapImage(new Uri($"pack://application:,,,/Resources/video-placeholder.png")), + Evaluate = bangumiFollow.Evaluate, + IndexShow = indexShow, + Progress = progress + }; + + Medias.Add(media); + + LoadingVisibility = Visibility.Collapsed; + NoDataVisibility = Visibility.Collapsed; + }); + + // 判断是否该结束线程,若为true,跳出循环 + if (cancellationToken.IsCancellationRequested) + { + break; + } + } + }, (tokenSource = new CancellationTokenSource()).Token); + + IsEnabled = true; + } + + /// + /// 初始化页面数据 + /// + private void InitView() + { + ArrowBack.Fill = DictionaryResource.GetColor("ColorTextDark"); + + ContentVisibility = Visibility.Collapsed; + LoadingVisibility = Visibility.Visible; + NoDataVisibility = Visibility.Collapsed; + + Medias.Clear(); + } + + /// + /// 导航到VideoDetail页面时执行 + /// + /// + public override void OnNavigatedTo(NavigationContext navigationContext) + { + base.OnNavigatedTo(navigationContext); + + // 根据传入参数不同执行不同任务 + mid = navigationContext.Parameters.GetValue("Parameter"); + if (mid == 0) + { + return; + } + + InitView(); + + // 初始选中项 + SelectTabId = 0; + + // 页面选择 + Pager = new CustomPagerViewModel(1, 1); + Pager.CurrentChanged += OnCurrentChanged_Pager; + Pager.CountChanged += OnCountChanged_Pager; + Pager.Current = 1; + } + + } +} diff --git a/DownKyi/ViewModels/ViewMyFavoritesViewModel.cs b/DownKyi/ViewModels/ViewMyFavoritesViewModel.cs index 8c2694a..4eb713d 100644 --- a/DownKyi/ViewModels/ViewMyFavoritesViewModel.cs +++ b/DownKyi/ViewModels/ViewMyFavoritesViewModel.cs @@ -15,6 +15,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -317,8 +318,12 @@ namespace DownKyi.ViewModels int i = 0; await Task.Run(() => { + // 为了避免执行其他操作时, + // Medias变化导致的异常 + var list = Medias.ToList(); + // 添加到下载 - foreach (var media in Medias) + foreach (var media in list) { // 只下载选中项,跳过未选中项 if (isOnlySelected && !media.IsSelected) { continue; } diff --git a/DownKyi/ViewModels/ViewMySpaceViewModel.cs b/DownKyi/ViewModels/ViewMySpaceViewModel.cs index a7e4c92..d5cbe0e 100644 --- a/DownKyi/ViewModels/ViewMySpaceViewModel.cs +++ b/DownKyi/ViewModels/ViewMySpaceViewModel.cs @@ -343,7 +343,7 @@ namespace DownKyi.ViewModels NavigateToView.NavigationView(eventAggregator, ViewMyFavoritesViewModel.Tag, Tag, mid); break; case 1: - Console.WriteLine(SelectedPackage); + NavigateToView.NavigationView(eventAggregator, ViewMyBangumiFollowViewModel.Tag, Tag, mid); break; case 2: Console.WriteLine(SelectedPackage); diff --git a/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs b/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs index a330123..d5ca22f 100644 --- a/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs +++ b/DownKyi/ViewModels/ViewPublicFavoritesViewModel.cs @@ -15,6 +15,7 @@ using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -249,8 +250,12 @@ namespace DownKyi.ViewModels int i = 0; await Task.Run(() => { + // 为了避免执行其他操作时, + // Medias变化导致的异常 + var list = FavoritesMedias.ToList(); + // 添加到下载 - foreach (FavoritesMedia media in FavoritesMedias) + foreach (var media in list) { // 只下载选中项,跳过未选中项 if (isOnlySelected && !media.IsSelected) { continue; } diff --git a/DownKyi/ViewModels/ViewPublicationViewModel.cs b/DownKyi/ViewModels/ViewPublicationViewModel.cs index ae0be55..37051d5 100644 --- a/DownKyi/ViewModels/ViewPublicationViewModel.cs +++ b/DownKyi/ViewModels/ViewPublicationViewModel.cs @@ -284,8 +284,12 @@ namespace DownKyi.ViewModels int i = 0; await Task.Run(() => { + // 为了避免执行其他操作时, + // Medias变化导致的异常 + var list = Medias.ToList(); + // 添加到下载 - foreach (var media in Medias) + foreach (var media in list) { // 只下载选中项,跳过未选中项 if (isOnlySelected && !media.IsSelected) { continue; } diff --git a/DownKyi/Views/ViewMyBangumiFollow.xaml b/DownKyi/Views/ViewMyBangumiFollow.xaml new file mode 100644 index 0000000..f6a0a5b --- /dev/null +++ b/DownKyi/Views/ViewMyBangumiFollow.xaml @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +