SimpleToDoList\Models\ToDoItem.cs
| |
| using CommunityToolkit.Mvvm.ComponentModel; |
| |
| namespace SimpleToDoList.Models; |
| |
| public class ToDoItem |
| { |
| public bool IsChecked { get; set; } |
| public string? Content { get; set; } |
| } |
| |
SimpleToDoList\Services\ToDoListFileService.cs
| |
| using System; |
| using System.Collections.Generic; |
| using System.IO; |
| using System.Text.Json; |
| using System.Threading.Tasks; |
| using SimpleToDoList.Models; |
| |
| namespace SimpleToDoList.Services; |
| |
| |
| |
| |
| public static class ToDoListFileService |
| { |
| |
| |
| private static string _jsonFileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Avalonia.SimpleToDoList", "MyToDoList.txt"); |
| |
| |
| |
| |
| |
| public static async Task SaveToFileAsync(IEnumerable<ToDoItem> itemsToSave) |
| { |
| |
| Directory.CreateDirectory(Path.GetDirectoryName(_jsonFileName)!); |
| |
| |
| using (var fs = File.Create(_jsonFileName)) |
| { |
| await JsonSerializer.SerializeAsync(fs, itemsToSave); |
| } |
| } |
| |
| |
| |
| |
| |
| public static async Task<IEnumerable<ToDoItem>?> LoadFromFileAsync() |
| { |
| try |
| { |
| |
| using (var fs = File.OpenRead(_jsonFileName)) |
| { |
| return await JsonSerializer.DeserializeAsync<IEnumerable<ToDoItem>>(fs); |
| } |
| } |
| catch (Exception e) when (e is FileNotFoundException || e is DirectoryNotFoundException) |
| { |
| |
| return null; |
| } |
| } |
| } |
| |
SimpleToDoList\ViewModels\MainViewModel.cs
| |
| using System.Collections.ObjectModel; |
| using Avalonia.Controls; |
| using CommunityToolkit.Mvvm.ComponentModel; |
| using CommunityToolkit.Mvvm.Input; |
| using SimpleToDoList.Models; |
| using SimpleToDoList.Services; |
| |
| namespace SimpleToDoList.ViewModels; |
| |
| public partial class MainViewModel : ViewModelBase |
| { |
| private string? _newItemContent; |
| public string? NewItemContent |
| { |
| get => _newItemContent; |
| set |
| { |
| if (SetProperty(ref _newItemContent, value)) |
| { |
| AddItemCommand.NotifyCanExecuteChanged(); |
| } |
| } |
| } |
| public ObservableCollection<ToDoItemViewModel> ToDoItems { get; } = new ObservableCollection<ToDoItemViewModel>(); |
| public IRelayCommand AddItemCommand { get; } |
| public IRelayCommand<ToDoItemViewModel> RemoveItemCommand { get; } |
| public MainViewModel() |
| { |
| AddItemCommand = new RelayCommand(AddItem, CanAddItem); |
| RemoveItemCommand = new RelayCommand<ToDoItemViewModel>(RemoveItem); |
| |
| if (Design.IsDesignMode) |
| { |
| ToDoItems = new ObservableCollection<ToDoItemViewModel>( |
| new[] |
| { |
| new ToDoItemViewModel() { Content = "Hello" }, |
| new ToDoItemViewModel() { Content = "Avalonia", IsChecked = true } |
| } |
| ); |
| } |
| } |
| |
| private void AddItem() |
| { |
| ToDoItems.Add(new ToDoItemViewModel() { Content = NewItemContent }); |
| NewItemContent = null; |
| } |
| |
| private bool CanAddItem() => !string.IsNullOrWhiteSpace(NewItemContent); |
| |
| private void RemoveItem(ToDoItemViewModel? item) |
| { |
| if (item == null) |
| return; |
| ToDoItems.Remove(item); |
| } |
| } |
| |
SimpleToDoList\ViewModels\ToDoItemViewModel.cs
| |
| using CommunityToolkit.Mvvm.ComponentModel; |
| using SimpleToDoList.Models; |
| |
| namespace SimpleToDoList.ViewModels; |
| |
| public partial class ToDoItemViewModel : ViewModelBase |
| { |
| private bool _isChecked; |
| private string? _content; |
| |
| public bool IsChecked |
| { |
| get => _isChecked; |
| set => SetProperty(ref _isChecked, value); |
| } |
| |
| public string? Content |
| { |
| get => _content; |
| set => SetProperty(ref _content, value); |
| } |
| |
| public ToDoItemViewModel() { } |
| |
| public ToDoItemViewModel(ToDoItem item) |
| { |
| IsChecked = item.IsChecked; |
| Content = item.Content; |
| } |
| |
| public ToDoItem GetToDoItem() |
| { |
| return new ToDoItem() { IsChecked = this.IsChecked, Content = this.Content }; |
| } |
| } |
| |
SimpleToDoList\ViewModels\ViewModelBase.cs
| |
| using CommunityToolkit.Mvvm.ComponentModel; |
| |
| namespace SimpleToDoList.ViewModels; |
| |
| public class ViewModelBase : ObservableObject { } |
| |
| |
SimpleToDoList\Views\MainWindow.axaml.cs
| |
| using System.Linq; |
| using Avalonia.Controls; |
| using SimpleToDoList.Services; |
| using SimpleToDoList.ViewModels; |
| |
| namespace SimpleToDoList.Views; |
| |
| public partial class MainWindow : Window |
| { |
| public MainWindow() |
| { |
| InitializeComponent(); |
| } |
| } |
SimpleToDoList\.csharpierrc.json
| |
| { |
| "printWidth": 200, |
| "useTabs": false, |
| "tabWidth": 4, |
| "endOfLine": "auto" |
| } |
| |
SimpleToDoList\App.axaml.cs
| |
| using System.Linq; |
| using System.Threading.Tasks; |
| using Avalonia; |
| using Avalonia.Controls.ApplicationLifetimes; |
| using Avalonia.Markup.Xaml; |
| using SimpleToDoList.Services; |
| using SimpleToDoList.ViewModels; |
| using SimpleToDoList.Views; |
| |
| namespace SimpleToDoList; |
| |
| public partial class App : Application |
| { |
| public override void Initialize() |
| { |
| AvaloniaXamlLoader.Load(this); |
| } |
| |
| |
| |
| private readonly MainViewModel _mainViewModel = new MainViewModel(); |
| |
| public override async void OnFrameworkInitializationCompleted() |
| { |
| if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) |
| { |
| desktop.MainWindow = new MainWindow |
| { |
| DataContext = _mainViewModel |
| }; |
| |
| |
| desktop.ShutdownRequested += DesktopOnShutdownRequested; |
| } |
| base.OnFrameworkInitializationCompleted(); |
| |
| |
| await InitMainViewModelAsync(); |
| } |
| |
| |
| |
| |
| private bool _canClose; |
| |
| private async void DesktopOnShutdownRequested(object? sender, ShutdownRequestedEventArgs e) |
| { |
| e.Cancel = !_canClose; |
| |
| if (!_canClose) |
| { |
| |
| var itemsToSave = _mainViewModel.ToDoItems.Select(item => item.GetToDoItem()); |
| |
| await ToDoListFileService.SaveToFileAsync(itemsToSave); |
| |
| |
| _canClose = true; |
| if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) |
| { |
| desktop.Shutdown(); |
| } |
| } |
| } |
| |
| |
| private async Task InitMainViewModelAsync() |
| { |
| |
| var itemsLoaded = await ToDoListFileService.LoadFromFileAsync(); |
| |
| if (itemsLoaded is not null) |
| { |
| foreach (var item in itemsLoaded) |
| { |
| _mainViewModel.ToDoItems.Add(new ToDoItemViewModel(item)); |
| } |
| } |
| } |
| } |
| |
SimpleToDoList\Program.cs
| |
| using System; |
| using Avalonia; |
| |
| namespace SimpleToDoList; |
| |
| sealed class Program |
| { |
| |
| |
| |
| [STAThread] |
| public static void Main(string[] args) => |
| BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); |
| |
| |
| public static AppBuilder BuildAvaloniaApp() => |
| AppBuilder.Configure<App>().UsePlatformDetect().WithInterFont().LogToTrace(); |
| } |
| |
SimpleToDoList\SimpleToDoList.csproj
| |
| <Project Sdk="Microsoft.NET.Sdk"> |
| <PropertyGroup> |
| <OutputType>WinExe</OutputType> |
| <TargetFramework>net6.0</TargetFramework> |
| <Nullable>enable</Nullable> |
| <BuiltInComInteropSupport>true</BuiltInComInteropSupport> |
| <ApplicationManifest>app.manifest</ApplicationManifest> |
| <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> |
| </PropertyGroup> |
| |
| <ItemGroup> |
| <AvaloniaResource Include="Assets\**"/> |
| </ItemGroup> |
| |
| |
| <ItemGroup> |
| <PackageReference Include="Avalonia" Version="11.0.5"/> |
| <PackageReference Include="Avalonia.Desktop" Version="11.0.5"/> |
| <PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.5"/> |
| <PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.5"/> |
| <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.--> |
| <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5"/> |
| <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" /> |
| </ItemGroup> |
| </Project> |
| |
SimpleToDoList\SimpleToDoList.sln
| |
| Microsoft Visual Studio Solution File, Format Version 12.00 |
| # Visual Studio Version 17 |
| VisualStudioVersion = 17.5.2.0 |
| MinimumVisualStudioVersion = 10.0.40219.1 |
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleToDoList", "SimpleToDoList.csproj", "{2B1D213D-DDB3-0066-BA10-EE293F7C9643}" |
| EndProject |
| Global |
| GlobalSection(SolutionConfigurationPlatforms) = preSolution |
| Debug|Any CPU = Debug|Any CPU |
| Release|Any CPU = Release|Any CPU |
| EndGlobalSection |
| GlobalSection(ProjectConfigurationPlatforms) = postSolution |
| {2B1D213D-DDB3-0066-BA10-EE293F7C9643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| {2B1D213D-DDB3-0066-BA10-EE293F7C9643}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| {2B1D213D-DDB3-0066-BA10-EE293F7C9643}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| {2B1D213D-DDB3-0066-BA10-EE293F7C9643}.Release|Any CPU.Build.0 = Release|Any CPU |
| EndGlobalSection |
| GlobalSection(SolutionProperties) = preSolution |
| HideSolutionNode = FALSE |
| EndGlobalSection |
| GlobalSection(ExtensibilityGlobals) = postSolution |
| SolutionGuid = {EB53C1D9-A334-4FD2-9BF0-DDC019E52625} |
| EndGlobalSection |
| EndGlobal |
| |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2023-02-18 fastapi_sqlalchemy_mysql_rbac_jwt_gooddemo
2023-02-18 opencv_人脸检测_学习笔记_读取图片_灰度转换_修改尺寸_绘制矩形_视频检测_训练数据