mirror of
https://gitcode.com/gh_mirrors/se/Semi.Avalonia
synced 2026-03-03 00:00:55 +08:00
Merge pull request #598 from irihitech/treedemo
Transfer TreeDataGrid demo
This commit is contained in:
@@ -39,8 +39,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.Demo.Drm", "d
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.TreeDataGrid", "src\Semi.Avalonia.TreeDataGrid\Semi.Avalonia.TreeDataGrid.csproj", "{398D2998-0835-41F5-99A3-608CAB8051E2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Semi.Avalonia.TreeDataGrid.Demo", "demo\Semi.Avalonia.TreeDataGrid.Demo\Semi.Avalonia.TreeDataGrid.Demo.csproj", "{6178B545-4BB6-458C-A27C-EE11F3885D38}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -84,10 +82,6 @@ Global
|
||||
{398D2998-0835-41F5-99A3-608CAB8051E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{398D2998-0835-41F5-99A3-608CAB8051E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{398D2998-0835-41F5-99A3-608CAB8051E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6178B545-4BB6-458C-A27C-EE11F3885D38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6178B545-4BB6-458C-A27C-EE11F3885D38}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6178B545-4BB6-458C-A27C-EE11F3885D38}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6178B545-4BB6-458C-A27C-EE11F3885D38}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -98,7 +92,6 @@ Global
|
||||
{D789AEDB-EBDF-4450-8E8E-B4A03FB257B0} = {43091528-9509-43CB-A003-9C5C11E96DD6}
|
||||
{0C81FC1C-5D2D-478A-9876-923A0C85EC2F} = {43091528-9509-43CB-A003-9C5C11E96DD6}
|
||||
{86D93406-412A-4429-93B2-92AAD0407784} = {43091528-9509-43CB-A003-9C5C11E96DD6}
|
||||
{6178B545-4BB6-458C-A27C-EE11F3885D38} = {43091528-9509-43CB-A003-9C5C11E96DD6}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7CA41ED3-2CED-40CC-AA21-28C3B42B1E86}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<semi:SemiPopupAnimations />
|
||||
<StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" />
|
||||
<StyleInclude Source="avares://Semi.Avalonia.ColorPicker/Index.axaml" />
|
||||
<StyleInclude Source="avares://Semi.Avalonia.TreeDataGrid/Index.axaml" />
|
||||
</Application.Styles>
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
@@ -5,7 +5,7 @@ using Avalonia;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo.Converters;
|
||||
namespace Semi.Avalonia.Demo.Converters;
|
||||
|
||||
public class FileIconConverter : IMultiValueConverter
|
||||
{
|
||||
127
demo/Semi.Avalonia.Demo/Pages/TreeDataGridDemo.axaml
Normal file
127
demo/Semi.Avalonia.Demo/Pages/TreeDataGridDemo.axaml
Normal file
@@ -0,0 +1,127 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:Semi.Avalonia.Demo.ViewModels"
|
||||
xmlns:converters="clr-namespace:Semi.Avalonia.Demo.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Semi.Avalonia.Demo.Pages.TreeDataGridDemo"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="vm:TreeDataGridDemoViewModel">
|
||||
<UserControl.Resources>
|
||||
<converters:FileIconConverter x:Key="FileIconConverter">
|
||||
<StaticResource x:Key="file" ResourceKey="SemiIconFile" />
|
||||
<StaticResource x:Key="folderOpen" ResourceKey="SemiIconFolderOpen" />
|
||||
<StaticResource x:Key="folderClosed" ResourceKey="SemiIconFolder" />
|
||||
</converters:FileIconConverter>
|
||||
</UserControl.Resources>
|
||||
<TabControl>
|
||||
<TabItem Header="Songs">
|
||||
<TreeDataGrid
|
||||
AutoDragDropRows="True"
|
||||
DataContext="{Binding SongsContext}"
|
||||
Source="{Binding Songs}">
|
||||
<TreeDataGrid.Resources>
|
||||
<DataTemplate x:Key="AlbumCell" DataType="vm:SongViewModel">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Text="{Binding Album}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="AlbumEditCell" DataType="vm:SongViewModel">
|
||||
<ComboBox
|
||||
VerticalAlignment="Center"
|
||||
Classes="Small"
|
||||
ItemsSource="{x:Static vm:Song.Albums}"
|
||||
SelectedItem="{Binding Album}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CommentsCell" DataType="vm:SongViewModel">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding CountOfComment}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CommentsEditCell" DataType="vm:SongViewModel">
|
||||
<NumericUpDown
|
||||
Width="100"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Small"
|
||||
Value="{Binding CountOfComment}" />
|
||||
</DataTemplate>
|
||||
</TreeDataGrid.Resources>
|
||||
<TreeDataGrid.Styles>
|
||||
<Style Selector="TreeDataGrid TreeDataGridRow:nth-last-child(2n)">
|
||||
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
|
||||
</Style>
|
||||
</TreeDataGrid.Styles>
|
||||
</TreeDataGrid>
|
||||
</TabItem>
|
||||
<TabItem Header="Files">
|
||||
<Grid DataContext="{Binding FilesContext}" RowDefinitions="Auto, *">
|
||||
<DockPanel Margin="0,4" DockPanel.Dock="Top">
|
||||
<ComboBox
|
||||
DockPanel.Dock="Left"
|
||||
ItemsSource="{Binding Drives}"
|
||||
SelectedItem="{Binding SelectedDrive}" />
|
||||
<TextBox
|
||||
Margin="4,0,0,0"
|
||||
VerticalContentAlignment="Center"
|
||||
KeyDown="SelectedPath_KeyDown"
|
||||
Text="{Binding SelectedPath, Mode=OneWay}" />
|
||||
</DockPanel>
|
||||
<TreeDataGrid
|
||||
Name="fileViewer"
|
||||
Grid.Row="1"
|
||||
Source="{Binding Source}">
|
||||
<TreeDataGrid.Resources>
|
||||
|
||||
<!-- Template for Name column cells -->
|
||||
<DataTemplate x:Key="FileNameCell" DataType="vm:FileNodeViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<PathIcon
|
||||
Theme="{StaticResource InnerPathIcon}"
|
||||
Margin="8,0">
|
||||
<PathIcon.Data>
|
||||
<MultiBinding Converter="{StaticResource FileIconConverter}">
|
||||
<Binding Path="IsDirectory" />
|
||||
<Binding Path="IsExpanded" />
|
||||
</MultiBinding>
|
||||
</PathIcon.Data>
|
||||
</PathIcon>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Edit template for Name column cells -->
|
||||
<DataTemplate x:Key="FileNameEditCell" DataType="vm:FileNodeViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Margin="0,0,4,0" VerticalAlignment="Center">
|
||||
<Image.Source>
|
||||
<MultiBinding Converter="{StaticResource FileIconConverter}">
|
||||
<Binding Path="IsDirectory" />
|
||||
<Binding Path="IsExpanded" />
|
||||
</MultiBinding>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<TextBox
|
||||
VerticalAlignment="Center"
|
||||
Classes="Small"
|
||||
Text="{Binding Name}">
|
||||
<TextBox.Styles>
|
||||
<Style Selector="DataValidationErrors">
|
||||
<Setter Property="Theme" Value="{DynamicResource TooltipDataValidationErrors}" />
|
||||
</Style>
|
||||
</TextBox.Styles>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</TreeDataGrid.Resources>
|
||||
<TreeDataGrid.Styles>
|
||||
<Style Selector="TreeDataGrid TreeDataGridRow:nth-child(2n)">
|
||||
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
|
||||
</Style>
|
||||
</TreeDataGrid.Styles>
|
||||
</TreeDataGrid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</UserControl>
|
||||
23
demo/Semi.Avalonia.Demo/Pages/TreeDataGridDemo.axaml.cs
Normal file
23
demo/Semi.Avalonia.Demo/Pages/TreeDataGridDemo.axaml.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Semi.Avalonia.Demo.ViewModels;
|
||||
|
||||
namespace Semi.Avalonia.Demo.Pages;
|
||||
|
||||
public partial class TreeDataGridDemo : UserControl
|
||||
{
|
||||
public TreeDataGridDemo()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DataContext = new TreeDataGridDemoViewModel();
|
||||
}
|
||||
|
||||
private void SelectedPath_KeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
var vm = DataContext as TreeDataGridDemoViewModel;
|
||||
vm.FilesContext.SelectedPath = (sender as TextBox)!.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
@@ -25,5 +25,6 @@
|
||||
<ProjectReference Include="..\..\src\Semi.Avalonia\Semi.Avalonia.csproj"/>
|
||||
<ProjectReference Include="..\..\src\Semi.Avalonia.ColorPicker\Semi.Avalonia.ColorPicker.csproj"/>
|
||||
<ProjectReference Include="..\..\src\Semi.Avalonia.DataGrid\Semi.Avalonia.DataGrid.csproj"/>
|
||||
<ProjectReference Include="..\..\src\Semi.Avalonia.TreeDataGrid\Semi.Avalonia.TreeDataGrid.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -59,6 +59,25 @@ public class Song
|
||||
Url = $"https://music.163.com/song?id={netEaseId}";
|
||||
}
|
||||
|
||||
public static List<string> Albums =>
|
||||
[
|
||||
"A.S.I.A",
|
||||
"饕餮人间",
|
||||
"七步咙咚呛",
|
||||
"大惊小怪",
|
||||
"The ONE",
|
||||
"以梦为马 (壮志骄阳版)",
|
||||
"emo了",
|
||||
"一眼万年",
|
||||
"冲刺吧",
|
||||
"爱的赏味期限",
|
||||
"COSMIC ANTHEM / 手紙",
|
||||
"世界晚安",
|
||||
"明年也要好好长大",
|
||||
"320万年前",
|
||||
"W.O.R.L.D."
|
||||
];
|
||||
|
||||
public static List<Song> Songs =>
|
||||
[
|
||||
new("好肚有肚(feat.李玲玉)", "熊猫堂ProducePandas", 2, 50, "A.S.I.A", 730, 1487039339),
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -11,43 +12,40 @@ using Avalonia.Controls.Selection;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo.ViewModels;
|
||||
namespace Semi.Avalonia.Demo.ViewModels;
|
||||
|
||||
public class FilesPageViewModel: ObservableObject
|
||||
public partial class FilesPageViewModel : ObservableObject
|
||||
{
|
||||
public IList<string> Drives { get; }
|
||||
private string _selectedDrive;
|
||||
private string? _selectedPath;
|
||||
private FileNodeViewModel? _root;
|
||||
public string SelectedDrive
|
||||
public HierarchicalTreeDataGridSource<FileNodeViewModel> Source { get; }
|
||||
[ObservableProperty] private string _selectedDrive;
|
||||
[ObservableProperty] private string? _selectedPath;
|
||||
[ObservableProperty] private FileNodeViewModel? _root;
|
||||
|
||||
partial void OnSelectedDriveChanged(string value)
|
||||
{
|
||||
get => _selectedDrive;
|
||||
set
|
||||
Root = new FileNodeViewModel(value, true, true);
|
||||
if (Source is not null)
|
||||
{
|
||||
SetProperty(ref _selectedDrive, value);
|
||||
_root = new FileNodeViewModel(_selectedDrive, isDirectory: true, isRoot: true);
|
||||
Source.Items = new[] { _root };
|
||||
Source.Items = [Root];
|
||||
}
|
||||
}
|
||||
|
||||
public string? SelectedPath
|
||||
partial void OnSelectedPathChanged(string? value)
|
||||
{
|
||||
get => _selectedPath;
|
||||
set => SetSelectedPath(value);
|
||||
SetSelectedPath(value);
|
||||
}
|
||||
|
||||
public HierarchicalTreeDataGridSource<FileNodeViewModel> Source { get; }
|
||||
|
||||
public FilesPageViewModel()
|
||||
{
|
||||
Drives= DriveInfo.GetDrives().Select(x => x.Name).ToList();
|
||||
Drives = DriveInfo.GetDrives().Select(x => x.Name).ToList();
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
_selectedDrive = "C:\\";
|
||||
SelectedDrive = @"C:\";
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedDrive = Drives.FirstOrDefault() ?? "/";
|
||||
SelectedDrive = Drives.FirstOrDefault() ?? "/";
|
||||
}
|
||||
|
||||
Source = new HierarchicalTreeDataGridSource<FileNodeViewModel>(Array.Empty<FileNodeViewModel>())
|
||||
@@ -58,7 +56,7 @@ public class FilesPageViewModel: ObservableObject
|
||||
null,
|
||||
x => x.IsChecked,
|
||||
(o, v) => o.IsChecked = v,
|
||||
options: new()
|
||||
options: new CheckBoxColumnOptions<FileNodeViewModel>
|
||||
{
|
||||
CanUserResizeColumn = false,
|
||||
}),
|
||||
@@ -68,20 +66,20 @@ public class FilesPageViewModel: ObservableObject
|
||||
"FileNameCell",
|
||||
"FileNameEditCell",
|
||||
new GridLength(1, GridUnitType.Star),
|
||||
new()
|
||||
new TemplateColumnOptions<FileNodeViewModel>
|
||||
{
|
||||
CompareAscending = FileNodeViewModel.SortAscending(x => x.Name),
|
||||
CompareDescending = FileNodeViewModel.SortDescending(x => x.Name),
|
||||
CompareAscending = FileNodeViewModel.SortAscending(vm => vm.Name),
|
||||
CompareDescending = FileNodeViewModel.SortDescending(vm => vm.Name),
|
||||
IsTextSearchEnabled = true,
|
||||
TextSearchValueSelector = x => x.Name
|
||||
TextSearchValueSelector = vm => vm.Name
|
||||
}),
|
||||
x => x.Children,
|
||||
x => x.HasChildren,
|
||||
x => x.IsExpanded),
|
||||
vm => vm.Children,
|
||||
vm => vm.HasChildren,
|
||||
vm => vm.IsExpanded),
|
||||
new TextColumn<FileNodeViewModel, long?>(
|
||||
"Size",
|
||||
x => x.Size,
|
||||
options: new()
|
||||
vm => vm.Size,
|
||||
options: new TextColumnOptions<FileNodeViewModel>
|
||||
{
|
||||
CompareAscending = FileNodeViewModel.SortAscending(x => x.Size),
|
||||
CompareDescending = FileNodeViewModel.SortDescending(x => x.Size),
|
||||
@@ -89,7 +87,7 @@ public class FilesPageViewModel: ObservableObject
|
||||
new TextColumn<FileNodeViewModel, DateTimeOffset?>(
|
||||
"Modified",
|
||||
x => x.Modified,
|
||||
options: new()
|
||||
options: new TextColumnOptions<FileNodeViewModel>
|
||||
{
|
||||
CompareAscending = FileNodeViewModel.SortAscending(x => x.Modified),
|
||||
CompareDescending = FileNodeViewModel.SortDescending(x => x.Modified),
|
||||
@@ -99,18 +97,18 @@ public class FilesPageViewModel: ObservableObject
|
||||
Source.RowSelection!.SingleSelect = false;
|
||||
Source.RowSelection.SelectionChanged += SelectionChanged;
|
||||
}
|
||||
|
||||
|
||||
private void SelectionChanged(object? sender, TreeSelectionModelSelectionChangedEventArgs<FileNodeViewModel> e)
|
||||
{
|
||||
var selectedPath = Source.RowSelection?.SelectedItem?.Path;
|
||||
this.SetProperty(ref _selectedPath, selectedPath, nameof(SelectedPath));
|
||||
|
||||
foreach (var i in e.DeselectedItems)
|
||||
System.Diagnostics.Trace.WriteLine($"Deselected '{i?.Path}'");
|
||||
Trace.WriteLine($"Deselected '{i?.Path}'");
|
||||
foreach (var i in e.SelectedItems)
|
||||
System.Diagnostics.Trace.WriteLine($"Selected '{i?.Path}'");
|
||||
Trace.WriteLine($"Selected '{i?.Path}'");
|
||||
}
|
||||
|
||||
|
||||
private void SetSelectedPath(string? value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
@@ -164,27 +162,28 @@ public class FilesPageViewModel: ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
Source.Items = [Root];
|
||||
Source.RowSelection!.SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileNodeViewModel: ObservableObject, IEditableObject
|
||||
public partial class FileNodeViewModel : ObservableObject, IEditableObject
|
||||
{
|
||||
private string _path;
|
||||
private string _name;
|
||||
[ObservableProperty] private string _path;
|
||||
[ObservableProperty] private string _name;
|
||||
private string? _undoName;
|
||||
private long? _size;
|
||||
private DateTimeOffset? _modified;
|
||||
[ObservableProperty] private long? _size;
|
||||
[ObservableProperty] private DateTimeOffset? _modified;
|
||||
private FileSystemWatcher? _watcher;
|
||||
private ObservableCollection<FileNodeViewModel>? _children;
|
||||
private bool _hasChildren = true;
|
||||
private bool _isExpanded;
|
||||
[ObservableProperty] private bool _hasChildren = true;
|
||||
[ObservableProperty] private bool _isExpanded;
|
||||
|
||||
public FileNodeViewModel( string path, bool isDirectory, bool isRoot = false)
|
||||
public FileNodeViewModel(string path, bool isDirectory, bool isRoot = false)
|
||||
{
|
||||
_path = path;
|
||||
_name = isRoot ? path : System.IO.Path.GetFileName(Path);
|
||||
_isExpanded = isRoot;
|
||||
Path = path;
|
||||
Name = isRoot ? path : System.IO.Path.GetFileName(Path);
|
||||
IsExpanded = isRoot;
|
||||
IsDirectory = isDirectory;
|
||||
HasChildren = isDirectory;
|
||||
|
||||
@@ -196,42 +195,6 @@ public class FileNodeViewModel: ObservableObject, IEditableObject
|
||||
}
|
||||
}
|
||||
|
||||
public string Path
|
||||
{
|
||||
get => _path;
|
||||
private set => SetProperty(ref _path, value);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
private set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
public long? Size
|
||||
{
|
||||
get => _size;
|
||||
private set => SetProperty(ref _size, value);
|
||||
}
|
||||
|
||||
public DateTimeOffset? Modified
|
||||
{
|
||||
get => _modified;
|
||||
private set => SetProperty(ref _modified, value);
|
||||
}
|
||||
|
||||
public bool HasChildren
|
||||
{
|
||||
get => _hasChildren;
|
||||
private set => SetProperty(ref _hasChildren, value);
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set => SetProperty(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public bool IsChecked { get; set; }
|
||||
public bool IsDirectory { get; }
|
||||
public IReadOnlyList<FileNodeViewModel> Children => _children ??= LoadChildren();
|
||||
@@ -332,6 +295,7 @@ public class FileNodeViewModel: ObservableObject, IEditableObject
|
||||
child.Size = info.Length;
|
||||
child.Modified = info.LastWriteTimeUtc;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -359,7 +323,7 @@ public class FileNodeViewModel: ObservableObject, IEditableObject
|
||||
if (_children[i].Path == e.FullPath)
|
||||
{
|
||||
_children.RemoveAt(i);
|
||||
System.Diagnostics.Debug.WriteLine($"Removed {e.FullPath}");
|
||||
Debug.WriteLine($"Removed {e.FullPath}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -394,6 +358,7 @@ internal static class ListExtensions
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Models.TreeDataGrid;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Semi.Avalonia.Demo.ViewModels;
|
||||
|
||||
public class SongsPageViewModel : ObservableObject
|
||||
{
|
||||
public FlatTreeDataGridSource<SongViewModel> Songs { get; }
|
||||
|
||||
public SongsPageViewModel()
|
||||
{
|
||||
var songs = new ObservableCollection<SongViewModel>(Song.Songs.Select(a => new SongViewModel()
|
||||
{
|
||||
Title = a.Title,
|
||||
Artist = a.Artist,
|
||||
Album = a.Album,
|
||||
CountOfComment = a.CountOfComment,
|
||||
IsSelected = false
|
||||
}));
|
||||
|
||||
Songs = new FlatTreeDataGridSource<SongViewModel>(songs)
|
||||
{
|
||||
Columns =
|
||||
{
|
||||
new CheckBoxColumn<SongViewModel>(
|
||||
"IsSelected",
|
||||
a => a.IsSelected,
|
||||
(model, b) => { model.IsSelected = b; },
|
||||
new GridLength(108, GridUnitType.Pixel)),
|
||||
new TextColumn<SongViewModel, string>(
|
||||
"Title",
|
||||
a => a.Title,
|
||||
(o, a) => o.Title = a,
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
new TextColumn<SongViewModel, string>("Artist",
|
||||
a => a.Artist,
|
||||
(o, a) => o.Artist = a,
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
new TemplateColumn<SongViewModel>("Album",
|
||||
"AlbumCell",
|
||||
"AlbumEditCell",
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
new TemplateColumn<SongViewModel>(
|
||||
"Comments",
|
||||
"CommentsCell",
|
||||
"CommentsEditCell",
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo.ViewModels;
|
||||
namespace Semi.Avalonia.Demo.ViewModels;
|
||||
|
||||
public class MainViewModel: ObservableObject
|
||||
public class TreeDataGridDemoViewModel: ObservableObject
|
||||
{
|
||||
public SongsPageViewModel SongsContext { get; } = new();
|
||||
public FilesPageViewModel FilesContext { get; } = new();
|
||||
@@ -135,6 +135,9 @@
|
||||
<TabItem Header="DataGrid">
|
||||
<pages:DataGridDemo />
|
||||
</TabItem>
|
||||
<TabItem Header="TreeDataGrid">
|
||||
<pages:TreeDataGridDemo />
|
||||
</TabItem>
|
||||
<TabItem
|
||||
Theme="{DynamicResource CategoryTabItem}"
|
||||
Header="Basic" />
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<Application
|
||||
x:Class="Semi.Avalonia.TreeDataGrid.Demo.App"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:semi="https://irihi.tech/semi">
|
||||
|
||||
<Application.Styles>
|
||||
<semi:SemiTheme Locale="zh-CN" />
|
||||
<StyleInclude Source="avares://Semi.Avalonia.TreeDataGrid/Index.axaml" />
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
@@ -1,23 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
desktop.MainWindow = new MainWindow();
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<Window
|
||||
x:Class="Semi.Avalonia.TreeDataGrid.Demo.MainWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Semi.Avalonia.TreeDataGrid.Demo.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="clr-namespace:Semi.Avalonia.TreeDataGrid.Demo.ViewModels;assembly=Semi.Avalonia.TreeDataGrid.Demo"
|
||||
Title="Semi.Avalonia.TreeDataGrid.Demo"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:DataType="vm:MainViewModel"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<converters:FileIconConverter x:Key="FileIconConverter">
|
||||
<StaticResource x:Key="file" ResourceKey="SemiIconFile" />
|
||||
<StaticResource x:Key="folderOpen" ResourceKey="SemiIconFolderOpen" />
|
||||
<StaticResource x:Key="folderClosed" ResourceKey="SemiIconFolder" />
|
||||
</converters:FileIconConverter>
|
||||
</Window.Resources>
|
||||
<Grid RowDefinitions="Auto, *">
|
||||
<Button
|
||||
HorizontalAlignment="Right"
|
||||
Click="Button_OnClick"
|
||||
Content="Theme" />
|
||||
<TabControl Grid.Row="1">
|
||||
<TabItem Header="Songs">
|
||||
<TreeDataGrid
|
||||
AutoDragDropRows="True"
|
||||
DataContext="{Binding SongsContext}"
|
||||
Source="{Binding Songs}">
|
||||
<TreeDataGrid.Resources>
|
||||
<DataTemplate x:Key="AlbumCell" DataType="vm:SongViewModel">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Text="{Binding Album}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="AlbumEditCell" DataType="vm:SongViewModel">
|
||||
<ComboBox
|
||||
VerticalAlignment="Center"
|
||||
Classes="Small"
|
||||
ItemsSource="{x:Static vm:Song.Albums}"
|
||||
SelectedItem="{Binding Album}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CommentsCell" DataType="vm:SongViewModel">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding CountOfComment}" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CommentsEditCell" DataType="vm:SongViewModel">
|
||||
<NumericUpDown
|
||||
Width="100"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Small"
|
||||
Value="{Binding CountOfComment}" />
|
||||
</DataTemplate>
|
||||
</TreeDataGrid.Resources>
|
||||
<TreeDataGrid.Styles>
|
||||
<Style Selector="TreeDataGrid TreeDataGridRow:nth-last-child(2n)">
|
||||
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
|
||||
</Style>
|
||||
</TreeDataGrid.Styles>
|
||||
</TreeDataGrid>
|
||||
</TabItem>
|
||||
<TabItem Header="Files">
|
||||
<Grid DataContext="{Binding FilesContext}" RowDefinitions="Auto, *">
|
||||
<DockPanel Margin="0,4" DockPanel.Dock="Top">
|
||||
<ComboBox
|
||||
DockPanel.Dock="Left"
|
||||
ItemsSource="{Binding Drives}"
|
||||
SelectedItem="{Binding SelectedDrive}" />
|
||||
<TextBox
|
||||
Margin="4,0,0,0"
|
||||
VerticalContentAlignment="Center"
|
||||
KeyDown="SelectedPath_KeyDown"
|
||||
Text="{Binding SelectedPath, Mode=OneWay}" />
|
||||
</DockPanel>
|
||||
<TreeDataGrid
|
||||
Name="fileViewer"
|
||||
Grid.Row="1"
|
||||
Source="{Binding Source}">
|
||||
<TreeDataGrid.Resources>
|
||||
|
||||
<!-- Template for Name column cells -->
|
||||
<DataTemplate x:Key="FileNameCell" DataType="vm:FileNodeViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<PathIcon
|
||||
Theme="{StaticResource InnerPathIcon}"
|
||||
Margin="8,0">
|
||||
<PathIcon.Data>
|
||||
<MultiBinding Converter="{StaticResource FileIconConverter}">
|
||||
<Binding Path="IsDirectory" />
|
||||
<Binding Path="IsExpanded" />
|
||||
</MultiBinding>
|
||||
</PathIcon.Data>
|
||||
</PathIcon>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Edit template for Name column cells -->
|
||||
<DataTemplate x:Key="FileNameEditCell" DataType="vm:FileNodeViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Margin="0,0,4,0" VerticalAlignment="Center">
|
||||
<Image.Source>
|
||||
<MultiBinding Converter="{StaticResource FileIconConverter}">
|
||||
<Binding Path="IsDirectory" />
|
||||
<Binding Path="IsExpanded" />
|
||||
</MultiBinding>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<TextBox
|
||||
VerticalAlignment="Center"
|
||||
Classes="Small"
|
||||
Text="{Binding Name}">
|
||||
<TextBox.Styles>
|
||||
<Style Selector="DataValidationErrors">
|
||||
<Setter Property="Theme" Value="{DynamicResource TooltipDataValidationErrors}" />
|
||||
</Style>
|
||||
</TextBox.Styles>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</TreeDataGrid.Resources>
|
||||
<TreeDataGrid.Styles>
|
||||
<Style Selector="TreeDataGrid TreeDataGridRow:nth-child(2n)">
|
||||
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
|
||||
</Style>
|
||||
</TreeDataGrid.Styles>
|
||||
</TreeDataGrid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,36 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Styling;
|
||||
using Semi.Avalonia.TreeDataGrid.Demo.ViewModels;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DataContext = new MainViewModel();
|
||||
}
|
||||
|
||||
private void Button_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app is not null)
|
||||
{
|
||||
var theme = app.ActualThemeVariant;
|
||||
app.RequestedThemeVariant = theme == ThemeVariant.Dark ? ThemeVariant.Light : ThemeVariant.Dark;
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectedPath_KeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
var vm = (MainViewModel)DataContext!;
|
||||
vm.FilesContext.SelectedPath = ((TextBox)sender!).Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo;
|
||||
|
||||
sealed class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
[STAThread]
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.With(new FontManagerOptions
|
||||
{
|
||||
FontFallbacks =
|
||||
[
|
||||
new FontFallback
|
||||
{
|
||||
FontFamily = new FontFamily("Microsoft YaHei")
|
||||
}
|
||||
]
|
||||
})
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.LogToTrace();
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<!-- Uncomment below to enable Native AOT compilation-->
|
||||
<!--<PublishAot>true</PublishAot>-->
|
||||
<!--<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>-->
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="../Directory.Build.props"/>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)"/>
|
||||
<PackageReference Include="Avalonia.Desktop" Version="$(AvaloniaVersion)"/>
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="$(AvaloniaVersion)">
|
||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="$(CommunityToolkitVersion)"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Semi.Avalonia.TreeDataGrid\Semi.Avalonia.TreeDataGrid.csproj"/>
|
||||
<ProjectReference Include="..\..\src\Semi.Avalonia\Semi.Avalonia.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,184 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Models.TreeDataGrid;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Semi.Avalonia.TreeDataGrid.Demo.ViewModels;
|
||||
|
||||
public class SongsPageViewModel: ObservableObject
|
||||
{
|
||||
private readonly ObservableCollection<SongViewModel> _songs;
|
||||
|
||||
public FlatTreeDataGridSource<SongViewModel> Songs { get; }
|
||||
|
||||
public SongsPageViewModel()
|
||||
{
|
||||
_songs = new ObservableCollection<SongViewModel>(Song.Songs.Select(a => new SongViewModel()
|
||||
{
|
||||
Title = a.Title, Artist = a.Artist, Album = a.Album, CountOfComment = a.CountOfComment,
|
||||
IsSelected = false
|
||||
}));
|
||||
|
||||
Songs = new FlatTreeDataGridSource<SongViewModel>(_songs)
|
||||
{
|
||||
Columns =
|
||||
{
|
||||
new CheckBoxColumn<SongViewModel>("IsSelected", a => a.IsSelected,
|
||||
(model, b) => { model.IsSelected = b; }, new GridLength(108, GridUnitType.Pixel)),
|
||||
new TextColumn<SongViewModel, string>("Title", a => a.Title, (o, a) => o.Title = a,
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
new TextColumn<SongViewModel, string>("Artist", a => a.Artist, (o, a) => o.Artist = a,
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
new TemplateColumn<SongViewModel>("Album", "AlbumCell", "AlbumEditCell",
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
new TemplateColumn<SongViewModel>("Comments", "CommentsCell", "CommentsEditCell",
|
||||
new GridLength(6, GridUnitType.Star)),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class Song
|
||||
{
|
||||
public string? Title { get; set; }
|
||||
public string? Artist { get; set; }
|
||||
public TimeSpan? Duration { get; set; }
|
||||
public string? Album { get; set; }
|
||||
public int? CountOfComment { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public Song(string title, string artist, int m, int s, string album, int countOfComment, int netEaseId)
|
||||
{
|
||||
Title = title;
|
||||
Artist = artist;
|
||||
Duration = new TimeSpan(0, m, s);
|
||||
Album = album;
|
||||
CountOfComment = countOfComment;
|
||||
Url = $"https://music.163.com/song?id={netEaseId}";
|
||||
|
||||
}
|
||||
|
||||
public static List<string> Albums { get; set; } = new List<string>()
|
||||
{
|
||||
"A.S.I.A",
|
||||
"饕餮人间",
|
||||
"七步咙咚呛",
|
||||
"大惊小怪",
|
||||
"The ONE",
|
||||
"以梦为马 (壮志骄阳版)",
|
||||
"emo了",
|
||||
"一眼万年",
|
||||
"冲刺吧",
|
||||
"爱的赏味期限",
|
||||
"COSMIC ANTHEM / 手紙",
|
||||
"世界晚安",
|
||||
"明年也要好好长大",
|
||||
"320万年前",
|
||||
"W.O.R.L.D.",
|
||||
};
|
||||
|
||||
public static List<Song> Songs { get; set; } = new List<Song>()
|
||||
{
|
||||
new("好肚有肚(feat.李玲玉)", "熊猫堂ProducePandas", 2, 50, "A.S.I.A", 730, 1487039339),
|
||||
new("荒诞秀", "熊猫堂ProducePandas", 3, 15, "A.S.I.A", 639, 1487037601),
|
||||
new("长大", "熊猫堂ProducePandas", 4, 6, "A.S.I.A", 1114, 1487037690),
|
||||
new("招财猫(feat.纪粹希(G-Tracy))", "熊猫堂ProducePandas", 3, 37, "A.S.I.A", 361, 1487039632),
|
||||
new("千转", "熊猫堂ProducePandas", 4, 0, "A.S.I.A", 1115, 1477312398),
|
||||
new("辣辣辣", "熊猫堂ProducePandas", 3, 24, "A.S.I.A", 1873, 1465043716),
|
||||
new("碎碎念", "熊猫堂ProducePandas", 3, 25, "A.S.I.A", 676, 1474142064),
|
||||
new("盘他", "熊猫堂ProducePandas", 2, 16, "A.S.I.A", 365, 1481652786),
|
||||
new("Na Na Na", "熊猫堂ProducePandas", 3, 26, "A.S.I.A", 312, 1469022662),
|
||||
new("Indigo", "熊猫堂ProducePandas", 3, 15, "A.S.I.A", 137, 1487039517),
|
||||
new("饕餮人间", "熊猫堂ProducePandas", 3, 20, "饕餮人间", 1295, 1499584605),
|
||||
new("七步咙咚呛", "熊猫堂ProducePandas", 3, 10, "七步咙咚呛", 175, 1809095152),
|
||||
new("大惊小怪", "熊猫堂ProducePandas", 3, 32, "大惊小怪", 10420, 1847477425),
|
||||
new("工具人", "熊猫堂ProducePandas", 2, 46, "大惊小怪", 1135, 1847476499),
|
||||
new("以梦为马", "熊猫堂ProducePandas", 4, 19, "大惊小怪", 18361, 1836034373),
|
||||
new("以梦为马(Piano Version)", "熊猫堂ProducePandas", 3, 4, "大惊小怪", 570, 1847477423),
|
||||
new("The ONE", "熊猫堂ProducePandas", 2, 58, "The ONE", 1508, 1864329424),
|
||||
new("The ONE(日文版)", "熊猫堂ProducePandas", 2, 57, "The ONE", 385, 1864329429),
|
||||
new("以梦为马 (壮志骄阳版)", "熊猫堂ProducePandas", 4, 19, "以梦为马 (壮志骄阳版)", 161, 1865138896),
|
||||
new("New Horse", "熊猫堂ProducePandas", 2, 30, "emo了", 643, 1887021307),
|
||||
new("不例外", "熊猫堂ProducePandas", 3, 31, "emo了", 1818, 1887022665),
|
||||
new("满意", "熊猫堂ProducePandas", 4, 32, "emo了", 1081, 1882433472),
|
||||
new("就算与全世界为敌也要跟你在一起", "熊猫堂ProducePandas", 3, 32, "emo了", 2119, 1881759960),
|
||||
new("The ONE", "熊猫堂ProducePandas", 2, 58, "emo了", 67, 1887022648),
|
||||
new("口香糖", "熊猫堂ProducePandas", 3, 10, "emo了", 2181, 1885502254),
|
||||
new("Suuuuuuper Mario", "熊猫堂ProducePandas", 3, 32, "emo了", 1010, 1887021318),
|
||||
new("饕餮人间", "熊猫堂ProducePandas", 3, 22, "emo了", 109, 1887021320),
|
||||
new("以梦为马 (壮志骄阳版)", "熊猫堂ProducePandas", 4, 21, "emo了", 34, 1887022666),
|
||||
new("The ONE(日文版)", "熊猫堂ProducePandas", 2, 57, "emo了", 27, 1887022646),
|
||||
new("满意(DJheap九天版)", "熊猫堂ProducePandas", 4, 31, "emo了", 31, 1901605941),
|
||||
new("一眼万年", "熊猫堂ProducePandas", 3, 54, "一眼万年", 20, 1922599361),
|
||||
new("冲刺", "熊猫堂ProducePandas", 3, 49, "冲刺吧", 1006, 1932878194),
|
||||
new("滴答滴", "熊猫堂ProducePandas", 2, 30, "爱的赏味期限", 86, 1957515790),
|
||||
new("热带季风", "熊猫堂ProducePandas", 2, 45, "爱的赏味期限", 212, 1957514964),
|
||||
new("渣", "熊猫堂ProducePandas", 3, 28, "爱的赏味期限", 22, 1957514965),
|
||||
new("独特", "熊猫堂ProducePandas", 3, 33, "爱的赏味期限", 62, 1957514966),
|
||||
new("雨后", "熊猫堂ProducePandas", 4, 15, "爱的赏味期限", 23, 1957514967),
|
||||
new("然后然后", "熊猫堂ProducePandas", 3, 50, "爱的赏味期限", 108, 1957514968),
|
||||
new("丢", "熊猫堂ProducePandas", 3, 26, "爱的赏味期限", 30, 1957515792),
|
||||
new("热带疾风(FACEVOID桃心连哥 Remix)", "熊猫堂ProducePandas", 3, 23, "爱的赏味期限", 55, 1957515793),
|
||||
new("COSMIC ANTHEM -Japanese Ver.-", "熊猫堂ProducePandas", 3, 11, "COSMIC ANTHEM / 手紙", 0, 1977171493),
|
||||
new("手紙 (「長大-You Raise Me Up-」-Japanese Ver.-)", "熊猫堂ProducePandas", 4, 11, "COSMIC ANTHEM / 手紙", 0,
|
||||
1977171494),
|
||||
new("COSMIC ANTHEM -Chinese Ver.-", "熊猫堂ProducePandas", 3, 31, "COSMIC ANTHEM / 手紙", 0, 1977172202),
|
||||
new("世界晚安", "熊猫堂ProducePandas", 2, 59, "世界晚安", 652, 1985063377),
|
||||
new("世界晚安(泰文版)", "熊猫堂ProducePandas", 2, 59, "世界晚安", 134, 1987842504),
|
||||
new("世界晚安(钢琴版)", "熊猫堂ProducePandas", 3, 2, "世界晚安", 76, 1990475933),
|
||||
new("世界晚安(泰文钢琴版)", "熊猫堂ProducePandas", 3, 2, "世界晚安", 29, 1990475934),
|
||||
new("世界晚安(DJ沈念版)", "熊猫堂ProducePandas", 3, 9, "世界晚安", 34, 2014263184),
|
||||
new("世界晚安(钢琴配乐)", "熊猫堂ProducePandas", 2, 59, "世界晚安", 11, 2014263185),
|
||||
new("明年也要好好长大", "熊猫堂ProducePandas", 3, 12, "明年也要好好长大", 0, 2010515162),
|
||||
new("320万年前(DJ沈念版)", "熊猫堂ProducePandas", 3, 21, "320万年前", 8, 2055888636),
|
||||
new("320万年前", "熊猫堂ProducePandas", 3, 7, "W.O.R.L.D.", 329, 2049770469),
|
||||
new("隐德来希", "熊猫堂ProducePandas", 3, 3, "W.O.R.L.D.", 594, 2061317924),
|
||||
new("孔明", "熊猫堂ProducePandas", 3, 59, "W.O.R.L.D.", 91, 2063175274),
|
||||
new("锦鲤卟噜噜", "熊猫堂ProducePandas", 3, 5, "W.O.R.L.D.", 67, 2059208262),
|
||||
new("指鹿为马", "熊猫堂ProducePandas", 3, 12, "W.O.R.L.D.", 74, 2063175272),
|
||||
new("热带季风Remix", "熊猫堂ProducePandas", 3, 22, "W.O.R.L.D.", 23, 2063173319),
|
||||
new("加州梦境", "熊猫堂ProducePandas", 2, 56, "W.O.R.L.D.", 1662, 2063173324),
|
||||
new("渐进自由", "熊猫堂ProducePandas", 4, 19, "W.O.R.L.D.", 124, 2063173321),
|
||||
new("世界所有的烂漫", "熊猫堂ProducePandas", 3, 30, "W.O.R.L.D.", 335, 2053388775),
|
||||
};
|
||||
}
|
||||
|
||||
public class SongViewModel: ObservableObject
|
||||
{
|
||||
private string? _title;
|
||||
private string? _artist;
|
||||
private string? _album;
|
||||
private int? _countOfComment;
|
||||
private bool? _isSelected;
|
||||
public string? Title
|
||||
{
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
public string? Artist
|
||||
{
|
||||
get => _artist;
|
||||
set => SetProperty(ref _artist, value);
|
||||
}
|
||||
public string? Album
|
||||
{
|
||||
get => _album;
|
||||
set => SetProperty(ref _album, value);
|
||||
}
|
||||
public int? CountOfComment
|
||||
{
|
||||
get => _countOfComment;
|
||||
set => SetProperty(ref _countOfComment, value);
|
||||
}
|
||||
public bool? IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => SetProperty(ref _isSelected, value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<!-- This manifest is used on Windows only.
|
||||
Don't remove it as it might cause problems with window transparency and embeded controls.
|
||||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
||||
<assemblyIdentity version="1.0.0.0" name="Semi.Avalonia.TreeDataGrid.Demo.Desktop"/>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- A list of the Windows versions that this application has been tested on
|
||||
and is designed to work with. Uncomment the appropriate elements
|
||||
and Windows will automatically select the most compatible environment. -->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
Reference in New Issue
Block a user