文件命名系统设置

croire 3 years ago
parent e781c72d68
commit a809245e95

@ -3,13 +3,14 @@
namespace DownKyi.Core.FileName
{
/// <summary>
/// 文件名的分隔符
/// 文件名字段
/// </summary>
public static class HyphenSeparated
{
// 文件名的分隔符
public static Dictionary<int, string> Hyphen = new Dictionary<int, string>()
{
{ 101, "/" },
{ 100, "/" },
{ 101, "_" },
{ 102, "-" },
{ 103, "+" },
@ -25,5 +26,6 @@ namespace DownKyi.Core.FileName
{ 113, "}" },
{ 114, " " },
};
}
}

@ -1,4 +1,5 @@
using System.Collections.Generic;
using DownKyi.Core.FileName;
using System.Collections.Generic;
namespace DownKyi.Core.Settings.Models
{
@ -7,12 +8,13 @@ namespace DownKyi.Core.Settings.Models
/// </summary>
public class VideoSettings
{
public VideoCodecs VideoCodecs { get; set; }
public int Quality { get; set; }
public int AudioQuality { get; set; }
public AllowStatus IsTranscodingFlvToMp4 { get; set; }
public string SaveVideoRootPath { get; set; }
public List<string> HistoryVideoRootPaths { get; set; }
public AllowStatus IsUseSaveVideoRootPath { get; set; }
public VideoCodecs VideoCodecs { get; set; } // AVC or HEVC
public int Quality { get; set; } // 画质
public int AudioQuality { get; set; } // 音质
public AllowStatus IsTranscodingFlvToMp4 { get; set; } // 是否将flv转为mp4
public string SaveVideoRootPath { get; set; } // 视频保存路径
public List<string> HistoryVideoRootPaths { get; set; } // 历史视频保存路径
public AllowStatus IsUseSaveVideoRootPath { get; set; } // 是否使用默认视频保存路径
public List<FileNamePart> FileNameParts { get; set; } // 文件命名格式
}
}

@ -1,4 +1,5 @@
using System;
using DownKyi.Core.FileName;
using System;
using System.Collections.Generic;
using System.IO;
@ -27,6 +28,20 @@ namespace DownKyi.Core.Settings
// 是否使用默认下载目录,如果是,则每次点击下载选中项时不再询问下载目录
private readonly AllowStatus isUseSaveVideoRootPath = AllowStatus.NO;
// 文件命名格式
private readonly List<FileNamePart> fileNameParts = new List<FileNamePart>
{
FileNamePart.MAIN_TITLE,
FileNamePart.SLASH,
FileNamePart.ORDER,
FileNamePart.HYPHEN,
FileNamePart.PAGE_TITLE,
FileNamePart.HYPHEN,
FileNamePart.VIDEO_QUALITY,
FileNamePart.HYPHEN,
FileNamePart.VIDEO_CODEC,
};
/// <summary>
/// 获取优先下载的视频编码
/// </summary>
@ -216,5 +231,32 @@ namespace DownKyi.Core.Settings
return SetSettings();
}
/// <summary>
/// 获取文件命名格式
/// </summary>
/// <returns></returns>
public List<FileNamePart> GetFileNameParts()
{
appSettings = GetSettings();
if (appSettings.Video.FileNameParts == null)
{
// 第一次获取,先设置默认值
SetFileNameParts(fileNameParts);
return fileNameParts;
}
return appSettings.Video.FileNameParts;
}
/// <summary>
/// 设置文件命名格式
/// </summary>
/// <param name="historyPaths"></param>
/// <returns></returns>
public bool SetFileNameParts(List<FileNamePart> fileNameParts)
{
appSettings.Video.FileNameParts = fileNameParts;
return SetSettings();
}
}
}

@ -92,6 +92,7 @@
<Compile Include="Models\DownloadStatus.cs" />
<Compile Include="Models\Favorites.cs" />
<Compile Include="Models\FavoritesMedia.cs" />
<Compile Include="Models\DisplayFileNamePart.cs" />
<Compile Include="Models\ParseScopeDisplay.cs" />
<Compile Include="Models\PlayStreamType.cs" />
<Compile Include="Models\Resolution.cs" />

@ -113,16 +113,22 @@
<system:String x:Key="Video">视频</system:String>
<system:String x:Key="FirstVideoCodecs">优先下载的视频编码:</system:String>
<system:String x:Key="FirstVideoQuality">优先下载的视频画质:</system:String>
<system:String x:Key="IsAddVideoOrder">启用视频编号</system:String>
<system:String x:Key="IsAddVideoOrderTip">勾选后,将为下载完成的视频的文件名添加上序号</system:String>
<system:String x:Key="IsTranscodingFlvToMp4">下载FLV视频后转码为mp4</system:String>
<system:String x:Key="IsUseDefaultDirectory">使用默认下载目录</system:String>
<system:String x:Key="DefaultDirectory">默认下载目录:</system:String>
<system:String x:Key="DefaultDirectoryTip">默认将文件下载到该文件夹中</system:String>
<system:String x:Key="ChangeDirectory">更改目录</system:String>
<system:String x:Key="IsCreateFolderForMedia">为不同视频分别创建文件夹</system:String>
<system:String x:Key="IsDownloadDanmaku">在下载视频的同时下载弹幕</system:String>
<system:String x:Key="IsDownloadCover">在下载视频的同时下载封面</system:String>
<system:String x:Key="FileNameParts">文件命名格式</system:String>
<system:String x:Key="FileName">文件名:</system:String>
<system:String x:Key="OptionalFields">可选字段:</system:String>
<system:String x:Key="DisplayOrder">序号</system:String>
<system:String x:Key="DisplayMainTitle">视频标题</system:String>
<system:String x:Key="DisplayPageTitle">分P标题</system:String>
<system:String x:Key="DisplayVideoZone">视频分区</system:String>
<system:String x:Key="DisplayAudioQuality">音质</system:String>
<system:String x:Key="DisplayVideoQuality">画质</system:String>
<system:String x:Key="DisplayVideoCodec">视频编码</system:String>
<system:String x:Key="DisplaySpace">空格</system:String>
<system:String x:Key="SettingDanmaku">弹幕</system:String>
<system:String x:Key="FilterType">按类型屏蔽</system:String>

@ -0,0 +1,17 @@
using DownKyi.Core.FileName;
using Prism.Mvvm;
namespace DownKyi.Models
{
public class DisplayFileNamePart : BindableBase
{
public FileNamePart Id { get; set; }
private string title;
public string Title
{
get => title;
set => SetProperty(ref title, value);
}
}
}

@ -1,5 +1,6 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 左侧导航栏 -->
<Style x:Key="LeftTabHeaderItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
@ -66,7 +67,7 @@
<Style x:Key="LeftTabHeaderStyle" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ControlTemplate TargetType="{x:Type ListBox}">
<Border
Padding="0"
Background="{DynamicResource BrushTabHeaderGrey}"
@ -81,4 +82,120 @@
</Setter>
</Style>
<!-- TAG样式1 -->
<Style x:Key="TagItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Margin="5,3"
Padding="8,2"
Background="{DynamicResource BrushPrimary}"
CornerRadius="10"
Cursor="Hand">
<ContentPresenter
Name="content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Title}" />
</Border>
<ControlTemplate.Triggers>
<!-- 顺序很重要,不能修改 -->
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimary}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TagStyle" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- TAG样式2 -->
<Style x:Key="TagItem2Style" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border
Name="Border"
Margin="5,3"
Padding="8,2"
Background="{DynamicResource BrushPrimary}"
CornerRadius="10"
Cursor="Hand">
<ContentPresenter
Name="content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Title}" />
</Border>
<ControlTemplate.Triggers>
<!-- 顺序很重要,不能修改 -->
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushBackgroundGrey}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource BrushPrimaryTranslucent}" />
<Setter Property="Foreground" Value="{DynamicResource BrushText}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Tag2Style" TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border
Padding="5"
Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource BrushBorder}"
BorderThickness="1"
CornerRadius="10">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled">
<WrapPanel
IsItemsHost="True"
Orientation="Horizontal"
ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

@ -1,4 +1,5 @@
using DownKyi.Core.Settings;
using DownKyi.Core.FileName;
using DownKyi.Core.Settings;
using DownKyi.Events;
using DownKyi.Models;
using DownKyi.Services;
@ -6,7 +7,9 @@ using DownKyi.Utils;
using Prism.Commands;
using Prism.Events;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace DownKyi.ViewModels.Settings
@ -47,13 +50,6 @@ namespace DownKyi.ViewModels.Settings
set => SetProperty(ref selectedVideoQuality, value);
}
private bool isAddVideoOrder;
public bool IsAddVideoOrder
{
get => isAddVideoOrder;
set => SetProperty(ref isAddVideoOrder, value);
}
private bool isTranscodingFlvToMp4;
public bool IsTranscodingFlvToMp4
{
@ -75,29 +71,23 @@ namespace DownKyi.ViewModels.Settings
set => SetProperty(ref saveVideoDirectory, value);
}
private bool isCreateFolderForMedia;
public bool IsCreateFolderForMedia
private ObservableCollection<DisplayFileNamePart> selectedFileName;
public ObservableCollection<DisplayFileNamePart> SelectedFileName
{
get => isCreateFolderForMedia;
set => SetProperty(ref isCreateFolderForMedia, value);
get => selectedFileName;
set => SetProperty(ref selectedFileName, value);
}
private bool isDownloadDanmaku;
public bool IsDownloadDanmaku
private ObservableCollection<DisplayFileNamePart> optionalFields;
public ObservableCollection<DisplayFileNamePart> OptionalFields
{
get => isDownloadDanmaku;
set => SetProperty(ref isDownloadDanmaku, value);
}
private bool isDownloadCover;
public bool IsDownloadCover
{
get => isDownloadCover;
set => SetProperty(ref isDownloadCover, value);
get => optionalFields;
set => SetProperty(ref optionalFields, value);
}
#endregion
public ViewVideoViewModel(IEventAggregator eventAggregator) : base(eventAggregator)
{
@ -113,6 +103,15 @@ namespace DownKyi.ViewModels.Settings
// 优先下载画质
VideoQualityList = new ResolutionService().GetResolution();
// 文件命名格式
SelectedFileName = new ObservableCollection<DisplayFileNamePart>();
OptionalFields = new ObservableCollection<DisplayFileNamePart>();
foreach (FileNamePart item in Enum.GetValues(typeof(FileNamePart)))
{
string display = DisplayFileNamePart(item);
OptionalFields.Add(new DisplayFileNamePart { Id = item, Title = display });
}
#endregion
}
@ -135,10 +134,6 @@ namespace DownKyi.ViewModels.Settings
int quality = SettingsManager.GetInstance().GetQuality();
SelectedVideoQuality = VideoQualityList.FirstOrDefault(t => { return t.Id == quality; });
//// 是否在下载的视频前增加序号
//AllowStatus isAddOrder = SettingsManager.GetInstance().IsAddOrder();
//IsAddVideoOrder = isAddOrder == AllowStatus.YES;
// 是否下载flv视频后转码为mp4
AllowStatus isTranscodingFlvToMp4 = SettingsManager.GetInstance().IsTranscodingFlvToMp4();
IsTranscodingFlvToMp4 = isTranscodingFlvToMp4 == AllowStatus.YES;
@ -150,17 +145,14 @@ namespace DownKyi.ViewModels.Settings
// 默认下载目录
SaveVideoDirectory = SettingsManager.GetInstance().GetSaveVideoRootPath();
//// 是否为不同视频分别创建文件夹
//AllowStatus isCreateFolderForMedia = SettingsManager.GetInstance().IsCreateFolderForMedia();
//IsCreateFolderForMedia = isCreateFolderForMedia == AllowStatus.YES;
//// 是否在下载视频的同时下载弹幕
//AllowStatus isDownloadDanmaku = SettingsManager.GetInstance().IsDownloadDanmaku();
//IsDownloadDanmaku = isDownloadDanmaku == AllowStatus.YES;
//// 是否在下载视频的同时下载封面
//AllowStatus isDownloadCover = SettingsManager.GetInstance().IsDownloadCover();
//IsDownloadCover = isDownloadCover == AllowStatus.YES;
// 文件命名格式
List<FileNamePart> fileNameParts = SettingsManager.GetInstance().GetFileNameParts();
SelectedFileName.Clear();
foreach (FileNamePart item in fileNameParts)
{
string display = DisplayFileNamePart(item);
SelectedFileName.Add(new DisplayFileNamePart { Id = item, Title = display });
}
isOnNavigatedTo = false;
}
@ -199,21 +191,6 @@ namespace DownKyi.ViewModels.Settings
PublishTip(isSucceed);
}
//// 是否在下载的视频前增加序号事件
//private DelegateCommand IisAddVideoOrderCommand;
//public DelegateCommand IsAddVideoOrderCommand => IisAddVideoOrderCommand ?? (IisAddVideoOrderCommand = new DelegateCommand(ExecuteIsAddVideoOrderCommand));
///// <summary>
///// 是否在下载的视频前增加序号事件
///// </summary>
//private void ExecuteIsAddVideoOrderCommand()
//{
// AllowStatus isAddOrder = IsAddVideoOrder ? AllowStatus.YES : AllowStatus.NO;
// bool isSucceed = SettingsManager.GetInstance().IsAddOrder(isAddOrder);
// PublishTip(isSucceed);
//}
// 是否下载flv视频后转码为mp4事件
private DelegateCommand isTranscodingFlvToMp4Command;
public DelegateCommand IsTranscodingFlvToMp4Command => isTranscodingFlvToMp4Command ?? (isTranscodingFlvToMp4Command = new DelegateCommand(ExecuteIsTranscodingFlvToMp4Command));
@ -265,50 +242,55 @@ namespace DownKyi.ViewModels.Settings
}
}
//// 是否为不同视频分别创建文件夹事件
//private DelegateCommand isCreateFolderForMediaCommand;
//public DelegateCommand IsCreateFolderForMediaCommand => isCreateFolderForMediaCommand ?? (isCreateFolderForMediaCommand = new DelegateCommand(ExecuteIsCreateFolderForMediaCommand));
///// <summary>
///// 是否为不同视频分别创建文件夹事件
///// </summary>
//private void ExecuteIsCreateFolderForMediaCommand()
//{
// AllowStatus isCreateFolderForMedia = IsCreateFolderForMedia ? AllowStatus.YES : AllowStatus.NO;
// bool isSucceed = SettingsManager.GetInstance().IsCreateFolderForMedia(isCreateFolderForMedia);
// PublishTip(isSucceed);
//}
//// 是否在下载视频的同时下载弹幕事件
//private DelegateCommand isDownloadDanmakuCommand;
//public DelegateCommand IsDownloadDanmakuCommand => isDownloadDanmakuCommand ?? (isDownloadDanmakuCommand = new DelegateCommand(ExecuteIsDownloadDanmakuCommand));
///// <summary>
///// 是否在下载视频的同时下载弹幕事件
///// </summary>
//private void ExecuteIsDownloadDanmakuCommand()
//{
// AllowStatus isDownloadDanmaku = IsDownloadDanmaku ? AllowStatus.YES : AllowStatus.NO;
// bool isSucceed = SettingsManager.GetInstance().IsDownloadDanmaku(isDownloadDanmaku);
// PublishTip(isSucceed);
//}
//// 是否在下载视频的同时下载封面事件
//private DelegateCommand isDownloadCoverCommand;
//public DelegateCommand IsDownloadCoverCommand => isDownloadCoverCommand ?? (isDownloadCoverCommand = new DelegateCommand(ExecuteIsDownloadCoverCommand));
///// <summary>
///// 是否在下载视频的同时下载封面事件
///// </summary>
//private void ExecuteIsDownloadCoverCommand()
//{
// AllowStatus isDownloadCover = IsDownloadCover ? AllowStatus.YES : AllowStatus.NO;
// bool isSucceed = SettingsManager.GetInstance().IsDownloadCover(isDownloadCover);
// PublishTip(isSucceed);
//}
// 选中文件名字段点击事件
private DelegateCommand<object> selectedFileNameCommand;
public DelegateCommand<object> SelectedFileNameCommand => selectedFileNameCommand ?? (selectedFileNameCommand = new DelegateCommand<object>(ExecuteSelectedFileNameCommand));
/// <summary>
/// 选中文件名字段点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteSelectedFileNameCommand(object parameter)
{
bool isSucceed = SelectedFileName.Remove((DisplayFileNamePart)parameter);
if (!isSucceed)
{
PublishTip(isSucceed);
return;
}
List<FileNamePart> fileName = new List<FileNamePart>();
foreach (DisplayFileNamePart item in SelectedFileName)
{
fileName.Add(item.Id);
}
isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName);
PublishTip(isSucceed);
}
// 可选文件名字段点击事件
private DelegateCommand<object> optionalFieldsCommand;
public DelegateCommand<object> OptionalFieldsCommand => optionalFieldsCommand ?? (optionalFieldsCommand = new DelegateCommand<object>(ExecuteOptionalFieldsCommand));
/// <summary>
/// 可选文件名字段点击事件
/// </summary>
/// <param name="parameter"></param>
private void ExecuteOptionalFieldsCommand(object parameter)
{
SelectedFileName.Add((DisplayFileNamePart)parameter);
List<FileNamePart> fileName = new List<FileNamePart>();
foreach (DisplayFileNamePart item in SelectedFileName)
{
fileName.Add(item.Id);
}
bool isSucceed = SettingsManager.GetInstance().SetFileNameParts(fileName);
PublishTip(isSucceed);
}
#endregion
@ -379,5 +361,51 @@ namespace DownKyi.ViewModels.Settings
}
}
/// <summary>
/// 文件名字段显示
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private string DisplayFileNamePart(FileNamePart item)
{
string display = string.Empty;
switch (item)
{
case FileNamePart.ORDER:
display = DictionaryResource.GetString("DisplayOrder");
break;
case FileNamePart.MAIN_TITLE:
display = DictionaryResource.GetString("DisplayMainTitle");
break;
case FileNamePart.PAGE_TITLE:
display = DictionaryResource.GetString("DisplayPageTitle");
break;
case FileNamePart.VIDEO_ZONE:
display = DictionaryResource.GetString("DisplayVideoZone");
break;
case FileNamePart.AUDIO_QUALITY:
display = DictionaryResource.GetString("DisplayAudioQuality");
break;
case FileNamePart.VIDEO_QUALITY:
display = DictionaryResource.GetString("DisplayVideoQuality");
break;
case FileNamePart.VIDEO_CODEC:
display = DictionaryResource.GetString("DisplayVideoCodec");
break;
}
if (((int)item) >= 100)
{
display = HyphenSeparated.Hyphen[(int)item];
}
if (display == " ")
{
display = DictionaryResource.GetString("DisplaySpace");
}
return display;
}
}
}

@ -129,6 +129,72 @@
</StackPanel>
</StackPanel>
<GroupBox
Margin="0,20,0,0"
Padding="10,10"
HorizontalAlignment="Stretch">
<GroupBox.Header>
<TextBlock
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FileNameParts}" />
</GroupBox.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource FileName}" />
<ListBox
x:Name="nameSelectedFileName"
Grid.Row="0"
Grid.Column="1"
Margin="0,0,0,20"
ItemContainerStyle="{StaticResource TagItem2Style}"
ItemsSource="{Binding SelectedFileName, Mode=TwoWay}"
SelectionMode="Single"
Style="{StaticResource Tag2Style}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectedFileNameCommand}" CommandParameter="{Binding ElementName=nameSelectedFileName, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
<TextBlock
Grid.Row="1"
Grid.Column="0"
FontSize="12"
Foreground="{DynamicResource BrushTextDark}"
Text="{DynamicResource OptionalFields}" />
<ListBox
Name="nameOptionalFields"
Grid.Row="1"
Grid.Column="1"
ItemContainerStyle="{StaticResource TagItem2Style}"
ItemsSource="{Binding OptionalFields, Mode=TwoWay}"
SelectionMode="Single"
Style="{StaticResource Tag2Style}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding OptionalFieldsCommand}" CommandParameter="{Binding ElementName=nameOptionalFields, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
</Grid>
</GroupBox>
</StackPanel>
</ScrollViewer>
</UserControl>

Loading…
Cancel
Save