添加首页搜索框服务、剪贴板服务,修复一些问题

This commit is contained in:
leiurayer 2023-07-28 00:15:04 +08:00
parent 9392c10779
commit f01c44a473
16 changed files with 407 additions and 61 deletions

View File

@ -50,13 +50,16 @@ public partial class SettingsManager
/// <returns></returns>
private AppSettings GetSettings()
{
if (appSettings != null) { return appSettings; }
try
{
var fileStream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var streamReader = new StreamReader(fileStream, System.Text.Encoding.UTF8);
string jsonWordTemplate = streamReader.ReadToEnd();
streamReader.Close();
fileStream.Close();
string jsonWordTemplate = string.Empty;
using (var stream = new FileStream(settingsName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
{
using var reader = new StreamReader(stream, System.Text.Encoding.UTF8);
jsonWordTemplate = reader.ReadToEnd();
}
#if DEBUG
#else

View File

@ -9,8 +9,12 @@ public class BaseServices
public INotificationEvent NotificationEvent { get; }
public IClipboardService ClipboardService { get; }
public IDictionaryResource DictionaryResource { get; }
public IMainSearchService MainSearchService { get; }
public INavigationService NavigationService { get; }
public IStoragePicker StoragePicker { get; }
@ -19,14 +23,18 @@ public class BaseServices
public BaseServices(IBroadcastEvent broadcastEvent,
INotificationEvent notificationEvent,
IClipboardService clipboardService,
IDictionaryResource dictionaryResource,
IMainSearchService mainSearchService,
INavigationService navigationService,
IStoragePicker storagePicker,
IStorageService storageService)
{
BroadcastEvent = broadcastEvent;
NotificationEvent = notificationEvent;
ClipboardService = clipboardService;
DictionaryResource = dictionaryResource;
MainSearchService = mainSearchService;
NavigationService = navigationService;
StoragePicker = storagePicker;
StorageService = storageService;

View File

@ -5,4 +5,4 @@ public interface INavigationAware
void OnNavigatedTo(Dictionary<string, object>? parameter);
void OnNavigatedFrom(Dictionary<string, object>? parameter);
}
}

View File

@ -11,7 +11,9 @@ public abstract class ViewModelBase : ObservableObject, INavigationAware
protected IBroadcastEvent BroadcastEvent => _baseServices.BroadcastEvent;
protected INotificationEvent NotificationEvent => _baseServices.NotificationEvent;
protected IClipboardService ClipboardService => _baseServices.ClipboardService;
protected IDictionaryResource DictionaryResource => _baseServices.DictionaryResource;
protected IMainSearchService MainSearchService => _baseServices.MainSearchService;
protected INavigationService NavigationService => _baseServices.NavigationService;
protected IStoragePicker StoragePicker => _baseServices.StoragePicker;
protected IStorageService StorageService => _baseServices.StorageService;

View File

@ -0,0 +1,6 @@
namespace Downkyi.UI.Services;
public interface IClipboardService
{
Task<string> GetTextAsync();
}

View File

@ -0,0 +1,28 @@
namespace Downkyi.UI.Services;
public interface IMainSearchService
{
/// <summary>
/// 解析支持的输入,
/// 支持的格式有:<para/>
/// av号av170001, AV170001, https://www.bilibili.com/video/av170001 <para/>
/// BV号BV17x411w7KC, https://www.bilibili.com/video/BV17x411w7KC, https://b23.tv/BV17x411w7KC <para/>
/// 番剧电影、电视剧ss号ss32982, SS32982, https://www.bilibili.com/bangumi/play/ss32982 <para/>
/// 番剧电影、电视剧ep号ep317925, EP317925, https://www.bilibili.com/bangumi/play/ep317925 <para/>
/// 番剧电影、电视剧md号md28228367, MD28228367, https://www.bilibili.com/bangumi/media/md28228367 <para/>
/// 课程ss号https://www.bilibili.com/cheese/play/ss205 <para/>
/// 课程ep号https://www.bilibili.com/cheese/play/ep3489 <para/>
/// 收藏夹ml1329019876, ML1329019876, https://www.bilibili.com/medialist/detail/ml1329019876, https://www.bilibili.com/medialist/play/ml1329019876/ <para/>
/// 用户空间uid928123, UID928123, uid:928123, UID:928123, https://space.bilibili.com/928123
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
bool BiliInput(string input);
/// <summary>
/// 搜索关键词
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
bool SearchKey(string input);
}

View File

@ -0,0 +1,140 @@
using Downkyi.Core.Bili.Utils;
using Downkyi.Core.Settings;
using Downkyi.Core.Settings.Models;
using Downkyi.UI.ViewModels.User;
using Downkyi.UI.ViewModels.Video;
namespace Downkyi.UI.Services;
public class MainSearchService : IMainSearchService
{
private readonly INavigationService NavigationService;
public MainSearchService(INavigationService navigationService)
{
NavigationService = navigationService;
}
public bool BiliInput(string input)
{
// 移除剪贴板id
//string validId = input.Replace(AppConstant.ClipboardId, "");
string validId = input;
// 参数
Dictionary<string, object> parameter = new()
{
{ "key", "MainSearchService" },
{ "value", new object() },
};
// 视频
if (ParseEntrance.IsAvId(validId))
{
parameter["value"] = $"{ParseEntrance.VideoUrl}{validId.ToLower()}";
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsAvUrl(validId))
{
parameter["value"] = validId;
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBvId(validId))
{
parameter["value"] = $"{ParseEntrance.VideoUrl}{input}";
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBvUrl(validId))
{
parameter["value"] = validId;
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
// 番剧(电影、电视剧)
else if (ParseEntrance.IsBangumiSeasonId(validId))
{
parameter["value"] = $"{ParseEntrance.BangumiUrl}{input.ToLower()}";
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBangumiSeasonUrl(validId))
{
parameter["value"] = validId;
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBangumiEpisodeId(validId))
{
parameter["value"] = $"{ParseEntrance.BangumiUrl}{input.ToLower()}";
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBangumiEpisodeUrl(validId))
{
parameter["value"] = validId;
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBangumiMediaId(validId))
{
parameter["value"] = $"{ParseEntrance.BangumiMediaUrl}{input.ToLower()}";
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
else if (ParseEntrance.IsBangumiMediaUrl(validId))
{
parameter["value"] = validId;
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
// 课程
else if (ParseEntrance.IsCheeseSeasonUrl(validId)
|| ParseEntrance.IsCheeseEpisodeUrl(validId))
{
parameter["value"] = validId;
NavigationService.ForwardAsync(VideoDetailViewModel.Key, parameter);
}
// 用户参数传入mid
else if (ParseEntrance.IsUserId(validId) || ParseEntrance.IsUserUrl(validId))
{
NavigateToViewUserSpace(ParseEntrance.GetUserId(input));
}
// 收藏夹
else if (ParseEntrance.IsFavoritesId(validId) || ParseEntrance.IsFavoritesUrl(validId))
{
parameter["value"] = ParseEntrance.GetFavoritesId(input);
NavigationService.ForwardAsync(PublicFavoritesViewModel.Key, parameter);
}
else
{
return false;
}
return true;
}
public bool SearchKey(string input)
{
// TODO
return false;
}
/// <summary>
/// 导航到用户空间,
/// 如果传入的mid与本地登录的mid一致
/// 则进入我的用户空间。
/// </summary>
/// <param name="mid"></param>
private void NavigateToViewUserSpace(long mid)
{
Dictionary<string, object> parameter = new()
{
{ "key", "MainSearchService" },
{ "value", mid },
};
UserInfoSettings userInfo = SettingsManager.GetInstance().GetUserInfo();
if (userInfo != null && userInfo.Mid == mid)
{
NavigationService.ForwardAsync(MySpaceViewModel.Key, parameter);
}
else
{
NavigationService.ForwardAsync(UserSpaceViewModel.Key, parameter);
}
}
}

View File

@ -1,15 +1,18 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Downkyi.Core.Bili;
using Downkyi.Core.Log;
using Downkyi.Core.Settings;
using Downkyi.Core.Settings.Models;
using Downkyi.Core.Storage;
using Downkyi.UI.Mvvm;
using Downkyi.UI.Services;
using Downkyi.UI.ViewModels.DownloadManager;
using Downkyi.UI.ViewModels.Login;
using Downkyi.UI.ViewModels.Settings;
using Downkyi.UI.ViewModels.Toolbox;
using Downkyi.UI.ViewModels.User;
using System.Text.RegularExpressions;
namespace Downkyi.UI.ViewModels;
@ -115,9 +118,29 @@ public partial class IndexViewModel : ViewModelBase
#region
/// <summary>
/// 进入B站链接的处理逻辑
/// 只负责处理输入,并跳转到视频详情页。<para/>
/// 不是支持的格式,则进入搜索页面。
/// </summary>
private void EnterBili()
{
NotificationEvent.Publish("Enter Bili!");
if (InputText == string.Empty)
{
return;
}
Log.Logger.Debug(InputText);
InputText = Regex.Replace(InputText, @"[【]*[^【]*[^】]*[】 ]", "");
bool isSupport = MainSearchService.BiliInput(InputText);
if (!isSupport)
{
// 关键词搜索
MainSearchService.SearchKey(InputText);
}
InputText = string.Empty;
}
private async Task UpdateUserInfo()

View File

@ -114,14 +114,11 @@ public partial class NetworkViewModel : BaseSettingsViewModel
for (int i = 1; i <= 10; i++) { Splits.Add(i); }
// Aria的日志等级
AriaLogLevels = new List<string>
{
"DEBUG",
"INFO",
"NOTICE",
"WARN",
"ERROR"
};
AriaLogLevels.Add("DEBUG");
AriaLogLevels.Add("INFO");
AriaLogLevels.Add("NOTICE");
AriaLogLevels.Add("WARN");
AriaLogLevels.Add("ERROR");
// Aria同时下载数
for (int i = 1; i <= 10; i++) { AriaMaxConcurrentDownloads.Add(i); }
@ -130,12 +127,9 @@ public partial class NetworkViewModel : BaseSettingsViewModel
for (int i = 1; i <= 10; i++) { AriaSplits.Add(i); }
// Aria文件预分配
AriaFileAllocations = new List<string>
{
"NONE",
"PREALLOC",
"FALLOC"
};
AriaFileAllocations.Add("NONE");
AriaFileAllocations.Add("PREALLOC");
AriaFileAllocations.Add("FALLOC");
#endregion
}
@ -288,10 +282,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel
/// </summary>
/// <param name="parameter"></param>
[RelayCommand]
private void SetMaxCurrentDownloads(object parameter)
private void SetMaxCurrentDownloads()
{
SelectedMaxCurrentDownload = (int)parameter;
bool isSucceed = SettingsManager.GetInstance().SetMaxCurrentDownloads(SelectedMaxCurrentDownload);
PublishTip(Key, isSucceed);
}
@ -301,10 +293,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel
/// </summary>
/// <param name="parameter"></param>
[RelayCommand]
private void SetSplits(object parameter)
private void SetSplits()
{
SelectedSplit = (int)parameter;
bool isSucceed = SettingsManager.GetInstance().SetSplit(SelectedSplit);
PublishTip(Key, isSucceed);
}
@ -389,9 +379,9 @@ public partial class NetworkViewModel : BaseSettingsViewModel
/// </summary>
/// <param name="parameter"></param>
[RelayCommand]
private void SetAriaLogLevels(string parameter)
private void SetAriaLogLevels()
{
var ariaLogLevel = parameter switch
var ariaLogLevel = SelectedAriaLogLevel switch
{
"DEBUG" => AriaConfigLogLevel.DEBUG,
"INFO" => AriaConfigLogLevel.INFO,
@ -409,10 +399,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel
/// </summary>
/// <param name="parameter"></param>
[RelayCommand]
private void SetAriaMaxConcurrentDownloads(object parameter)
private void SetAriaMaxConcurrentDownloads()
{
SelectedAriaMaxConcurrentDownload = (int)parameter;
bool isSucceed = SettingsManager.GetInstance().SetMaxCurrentDownloads(SelectedAriaMaxConcurrentDownload);
PublishTip(Key, isSucceed);
}
@ -422,10 +410,8 @@ public partial class NetworkViewModel : BaseSettingsViewModel
/// </summary>
/// <param name="parameter"></param>
[RelayCommand]
private void SetAriaSplits(object parameter)
private void SetAriaSplits()
{
SelectedAriaSplit = (int)parameter;
bool isSucceed = SettingsManager.GetInstance().SetAriaSplit(SelectedAriaSplit);
PublishTip(Key, isSucceed);
}
@ -498,11 +484,10 @@ public partial class NetworkViewModel : BaseSettingsViewModel
/// <summary>
/// Aria文件预分配事件
/// </summary>
/// <param name="parameter"></param>
[RelayCommand]
private void SetAriaFileAllocations(string parameter)
private void SetAriaFileAllocations()
{
var ariaFileAllocation = parameter switch
var ariaFileAllocation = SelectedAriaFileAllocation switch
{
"NONE" => AriaConfigFileAllocation.NONE,
"PREALLOC" => AriaConfigFileAllocation.PREALLOC,

View File

@ -0,0 +1,29 @@
using CommunityToolkit.Mvvm.Input;
using Downkyi.UI.Mvvm;
namespace Downkyi.UI.ViewModels.Video;
public partial class PublicFavoritesViewModel : ViewModelBase
{
public const string Key = "PublicFavorites";
public PublicFavoritesViewModel(BaseServices baseServices) : base(baseServices)
{
}
#region
[RelayCommand(FlowExceptionsToTaskScheduler = true)]
private async Task BackwardAsync()
{
Dictionary<string, object> parameter = new()
{
{ "key", Key },
};
await NavigationService.BackwardAsync(parameter);
}
#endregion
}

View File

@ -0,0 +1,29 @@
using CommunityToolkit.Mvvm.Input;
using Downkyi.UI.Mvvm;
namespace Downkyi.UI.ViewModels.Video;
public partial class VideoDetailViewModel : ViewModelBase
{
public const string Key = "VideoDetail";
public VideoDetailViewModel(BaseServices baseServices) : base(baseServices)
{
}
#region
[RelayCommand(FlowExceptionsToTaskScheduler = true)]
private async Task BackwardAsync()
{
Dictionary<string, object> parameter = new()
{
{ "key", Key },
};
await NavigationService.BackwardAsync(parameter);
}
#endregion
}

View File

@ -9,6 +9,7 @@ using Downkyi.UI.ViewModels.Login;
using Downkyi.UI.ViewModels.Settings;
using Downkyi.UI.ViewModels.Toolbox;
using Downkyi.UI.ViewModels.User;
using Downkyi.UI.ViewModels.Video;
using Downkyi.ViewModels;
using Downkyi.ViewModels.Login;
using Downkyi.ViewModels.Settings;
@ -92,31 +93,41 @@ public static class ServiceLocator
.AddScoped<BaseServices>()
.AddSingleton<IBroadcastEvent, BroadcastEvent>()
.AddSingleton<INotificationEvent, NotificationEvent>()
.AddSingleton<IClipboardService, ClipboardService>()
.AddSingleton<IDictionaryResource, DictionaryResource>()
.AddSingleton<IMainSearchService, MainSearchService>()
.AddSingleton<INavigationService, NavigationService>()
.AddSingleton<IStoragePicker, StoragePicker>()
.AddSingleton<IStorageService, StorageService>()
//ViewModels
.AddSingleton<MainWindowViewModel>()
.AddSingleton<IndexViewModel>()
//
.AddSingleton<DownloadManagerViewModel>()
.AddSingleton<DownloadingViewModel>()
.AddSingleton<DownloadFinishedViewModel>()
//
.AddSingleton<LoginViewModel>()
.AddSingleton<QRCodeViewModelProxy>()
.AddSingleton<CookiesViewModel>()
.AddSingleton<MySpaceViewModel>()
.AddSingleton<UserSpaceViewModel>()
//
.AddSingleton<SettingsViewModel>()
.AddSingleton<BasicViewModel>()
.AddSingleton<NetworkViewModel>()
.AddSingleton<VideoViewModelProxy>()
.AddSingleton<DanmakuViewModelProxy>()
.AddSingleton<AboutViewModelProxy>()
.AddSingleton<DownloadManagerViewModel>()
.AddSingleton<DownloadingViewModel>()
.AddSingleton<DownloadFinishedViewModel>()
//
.AddSingleton<ToolboxViewModel>()
.AddSingleton<BiliHelperViewModel>()
.AddSingleton<DelogoViewModelProxy>()
.AddSingleton<ExtractMediaViewModelProxy>()
//
.AddSingleton<MySpaceViewModel>()
.AddSingleton<UserSpaceViewModel>()
//
.AddSingleton<VideoDetailViewModel>()
.AddSingleton<PublicFavoritesViewModel>()
.BuildServiceProvider());
}
}

View File

@ -0,0 +1,19 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Downkyi.UI.Services;
using System;
using System.Threading.Tasks;
namespace Downkyi.Services;
public class ClipboardService : IClipboardService
{
public async Task<string> GetTextAsync()
{
if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop ||
desktop.MainWindow?.Clipboard is not { } provider)
throw new NullReferenceException("Missing Clipboard instance.");
return await provider.GetTextAsync() ?? string.Empty;
}
}

View File

@ -1,5 +1,10 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Input;
using Downkyi.Core.Settings;
using Downkyi.Core.Settings.Enum;
using Downkyi.Core.Utils;
using Downkyi.UI.Mvvm;
using Downkyi.UI.ViewModels;
@ -8,8 +13,10 @@ using Downkyi.UI.ViewModels.Login;
using Downkyi.UI.ViewModels.Settings;
using Downkyi.UI.ViewModels.Toolbox;
using Downkyi.UI.ViewModels.User;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Downkyi.ViewModels;
@ -19,6 +26,8 @@ public partial class MainWindowViewModel : ViewModelBase
private readonly LinkStack<string> _pages = new();
private readonly CancellationTokenSource? tokenSource;
#region
[ObservableProperty]
@ -55,8 +64,61 @@ public partial class MainWindowViewModel : ViewModelBase
MessageVisibility = false;
});
// 监听剪贴板线程
string oldClip = string.Empty;
Task.Run(async () =>
{
CancellationToken cancellationToken = tokenSource!.Token;
if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop ||
desktop.MainWindow?.Clipboard is not { } provider)
throw new NullReferenceException("Missing Clipboard instance.");
await provider.SetTextAsync(oldClip);
while (true)
{
AllowStatus isListenClipboard = SettingsManager.GetInstance().IsListenClipboard();
if (isListenClipboard != AllowStatus.YES)
{
continue;
}
// 判断是否该结束线程若为true跳出while循环
if (cancellationToken.IsCancellationRequested)
{
break;
}
else
{
string clip = await ClipboardService.GetTextAsync();
if (clip.Equals(oldClip))
{
await Task.Delay(100);
continue;
}
oldClip = clip;
MainSearchService.BiliInput(clip);
}
}
}, (tokenSource = new CancellationTokenSource()).Token);
}
#region
/// <summary>
/// 退出窗口时执行
/// </summary>
[RelayCommand]
private void OnClosing()
{
// 取消任务
tokenSource?.Cancel();
}
#endregion
public void Forward(string viewKey, Dictionary<string, object>? parameter = null)
{
var viewModel = SetContent(viewKey);

View File

@ -2,6 +2,8 @@
x:Class="Downkyi.Views.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"
xmlns:local="using:Downkyi"
xmlns:vm="using:Downkyi.ViewModels"
Title="{DynamicResource AppName}"
@ -14,6 +16,11 @@
Design.DataContext="{x:Static local:ServiceLocator.MainWindowViewModel}"
Icon="/Assets/logo.ico"
WindowStartupLocation="CenterScreen">
<i:Interaction.Behaviors>
<ia:EventTriggerBehavior EventName="Closing">
<ia:InvokeCommandAction Command="{Binding ClosingCommand}" />
</ia:EventTriggerBehavior>
</i:Interaction.Behaviors>
<Grid>
<ContentControl Content="{Binding Content}" />

View File

@ -87,15 +87,14 @@
VerticalAlignment="Center"
Text="{DynamicResource MaxCurrentDownloads}" />
<ComboBox
Name="maxCurrentDownloads"
Width="100"
VerticalContentAlignment="Center"
Classes="normal"
ItemsSource="{Binding MaxCurrentDownloads}"
SelectedValue="{Binding SelectedMaxCurrentDownload}">
SelectedItem="{Binding SelectedMaxCurrentDownload}">
<i:Interaction.Behaviors>
<iac:ValueChangedTriggerBehavior Binding="{Binding SelectedMaxCurrentDownload}">
<ia:InvokeCommandAction Command="{Binding SetMaxCurrentDownloadsCommand}" CommandParameter="{Binding ElementName=maxCurrentDownloads, Path=SelectedValue}" />
<ia:InvokeCommandAction Command="{Binding SetMaxCurrentDownloadsCommand}" />
</iac:ValueChangedTriggerBehavior>
</i:Interaction.Behaviors>
</ComboBox>
@ -107,15 +106,14 @@
VerticalAlignment="Center"
Text="{DynamicResource Split}" />
<ComboBox
Name="splits"
Width="100"
VerticalContentAlignment="Center"
Classes="normal"
ItemsSource="{Binding Splits}"
SelectedValue="{Binding SelectedSplit}">
SelectedItem="{Binding SelectedSplit}">
<i:Interaction.Behaviors>
<iac:ValueChangedTriggerBehavior Binding="{Binding SelectedSplit}">
<ia:InvokeCommandAction Command="{Binding SetSplitsCommand}" CommandParameter="{Binding ElementName=splits, Path=SelectedValue}" />
<ia:InvokeCommandAction Command="{Binding SetSplitsCommand}" />
</iac:ValueChangedTriggerBehavior>
</i:Interaction.Behaviors>
</ComboBox>
@ -203,15 +201,14 @@
VerticalAlignment="Center"
Text="{DynamicResource AriaLogLevel}" />
<ComboBox
Name="ariaLogLevels"
Width="100"
VerticalContentAlignment="Center"
Classes="normal"
ItemsSource="{Binding AriaLogLevels}"
SelectedValue="{Binding SelectedAriaLogLevel}">
SelectedItem="{Binding SelectedAriaLogLevel}">
<i:Interaction.Behaviors>
<iac:ValueChangedTriggerBehavior Binding="{Binding SelectedAriaLogLevel}">
<ia:InvokeCommandAction Command="{Binding SetAriaLogLevelsCommand}" CommandParameter="{Binding ElementName=ariaLogLevels, Path=SelectedValue}" />
<ia:InvokeCommandAction Command="{Binding SetAriaLogLevelsCommand}" />
</iac:ValueChangedTriggerBehavior>
</i:Interaction.Behaviors>
</ComboBox>
@ -223,15 +220,14 @@
VerticalAlignment="Center"
Text="{DynamicResource AriaMaxConcurrentDownloads}" />
<ComboBox
Name="ariaMaxConcurrentDownloads"
Width="100"
VerticalContentAlignment="Center"
Classes="normal"
ItemsSource="{Binding AriaMaxConcurrentDownloads}"
SelectedValue="{Binding SelectedAriaMaxConcurrentDownload}">
SelectedItem="{Binding SelectedAriaMaxConcurrentDownload}">
<i:Interaction.Behaviors>
<iac:ValueChangedTriggerBehavior Binding="{Binding SelectedAriaMaxConcurrentDownload}">
<ia:InvokeCommandAction Command="{Binding SetAriaMaxConcurrentDownloadsCommand}" CommandParameter="{Binding ElementName=ariaMaxConcurrentDownloads, Path=SelectedValue}" />
<ia:InvokeCommandAction Command="{Binding SetAriaMaxConcurrentDownloadsCommand}" />
</iac:ValueChangedTriggerBehavior>
</i:Interaction.Behaviors>
</ComboBox>
@ -243,15 +239,14 @@
VerticalAlignment="Center"
Text="{DynamicResource AriaSplit}" />
<ComboBox
Name="ariaSplits"
Width="100"
VerticalContentAlignment="Center"
Classes="normal"
ItemsSource="{Binding AriaSplits}"
SelectedValue="{Binding SelectedAriaSplit}">
SelectedItem="{Binding SelectedAriaSplit}">
<i:Interaction.Behaviors>
<iac:ValueChangedTriggerBehavior Binding="{Binding SelectedAriaSplit}">
<ia:InvokeCommandAction Command="{Binding SetAriaSplitsCommand}" CommandParameter="{Binding ElementName=ariaSplits, Path=SelectedValue}" />
<ia:InvokeCommandAction Command="{Binding SetAriaSplitsCommand}" />
</iac:ValueChangedTriggerBehavior>
</i:Interaction.Behaviors>
</ComboBox>
@ -376,7 +371,6 @@
VerticalAlignment="Center"
Text="{DynamicResource AriaFileAllocation}" />
<ComboBox
Name="ariaFileAllocations"
Width="100"
VerticalContentAlignment="Center"
Classes="normal"
@ -384,7 +378,7 @@
SelectedValue="{Binding SelectedAriaFileAllocation}">
<i:Interaction.Behaviors>
<iac:ValueChangedTriggerBehavior Binding="{Binding SelectedAriaFileAllocation}">
<ia:InvokeCommandAction Command="{Binding SetAriaFileAllocationsCommand}" CommandParameter="{Binding ElementName=ariaFileAllocations, Path=SelectedValue}" />
<ia:InvokeCommandAction Command="{Binding SetAriaFileAllocationsCommand}" />
</iac:ValueChangedTriggerBehavior>
</i:Interaction.Behaviors>
</ComboBox>