This commit is contained in:
Matthew Parker
2023-08-31 21:37:54 +10:00
parent 0a7f1c072e
commit 701218a28b
21 changed files with 55 additions and 41 deletions

View File

@@ -0,0 +1,8 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="DotNetSolutionTools.App.App"
RequestedThemeVariant="Default">
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>

View File

@@ -0,0 +1,25 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using DotNetSolutionTools.App.ViewModels;
using DotNetSolutionTools.App.Views;
namespace DotNetSolutionTools.App;
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() { DataContext = new MainWindowViewModel() };
}
base.OnFrameworkInitializationCompleted();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>
<ItemGroup>
<ProjectCapability Include="Avalonia"/>
<TrimmerRootAssembly Include="Avalonia.Themes.Fluent"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0-preview8"/>
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview8"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.0-preview8"/>
<!--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.0-preview8"/>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DotNetSolutionTools.Core\DotNetSolutionTools.Core.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,18 @@
using System;
using Avalonia;
namespace DotNetSolutionTools.App;
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().StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>().UsePlatformDetect().WithInterFont().LogToTrace();
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DotNetSolutionTools.Core;
namespace DotNetSolutionTools.App.ViewModels;
public partial class MainWindowViewModel : ViewModelBase
{
[ObservableProperty]
private string _solutionFolderPath;
[ObservableProperty]
private string _solutionFilePath;
[ObservableProperty]
private string? _fileText;
[ObservableProperty]
private ObservableCollection<string> _parityResults = new ObservableCollection<string>()
{
"Test"
};
[RelayCommand]
private async Task ExecuteParityChecker(CancellationToken token)
{
var results =
DotNetSolutionTools.Core.SolutionParityChecker.CompareSolutionAndCSharpProjects(
SolutionFolderPath,
SolutionFilePath
);
ParityResults.Clear();
foreach (var result in results)
{
ParityResults.Add(result);
}
}
[RelayCommand]
private async Task FormatCsProjFile(CancellationToken token)
{
FormatCsproj.FormatCsprojFile(SolutionFilePath);
}
[RelayCommand]
private async Task LoadSolutionFile(CancellationToken token)
{
ErrorMessages?.Clear();
try
{
var file = await DoOpenFilePickerAsync();
if (file is null)
return;
SolutionFilePath = file.Path.AbsolutePath;
}
catch (Exception e)
{
ErrorMessages?.Add(e.Message);
}
}
[RelayCommand]
private async Task LoadSolutionFolder(CancellationToken token)
{
ErrorMessages?.Clear();
try
{
var folder = await DoOpenFolderPickerAsync();
if (folder is null)
return;
SolutionFolderPath = folder.Path.AbsolutePath;
}
catch (Exception e)
{
ErrorMessages?.Add(e.Message);
}
}
private async Task<IStorageFile?> DoOpenFilePickerAsync()
{
// For learning purposes, we opted to directly get the reference
// for StorageProvider APIs here inside the ViewModel.
// For your real-world apps, you should follow the MVVM principles
// by making service classes and locating them with DI/IoC.
// See IoCFileOps project for an example of how to accomplish this.
if (
Application.Current?.ApplicationLifetime
is not IClassicDesktopStyleApplicationLifetime desktop
|| desktop.MainWindow?.StorageProvider is not { } provider
)
throw new NullReferenceException("Missing StorageProvider instance.");
var files = await provider.OpenFilePickerAsync(
new FilePickerOpenOptions() { Title = "Open Text File", AllowMultiple = false }
);
return files?.Count >= 1 ? files[0] : null;
}
private async Task<IStorageFolder?> DoOpenFolderPickerAsync()
{
// For learning purposes, we opted to directly get the reference
// for StorageProvider APIs here inside the ViewModel.
// For your real-world apps, you should follow the MVVM principles
// by making service classes and locating them with DI/IoC.
// See IoCFileOps project for an example of how to accomplish this.
if (
Application.Current?.ApplicationLifetime
is not IClassicDesktopStyleApplicationLifetime desktop
|| desktop.MainWindow?.StorageProvider is not { } provider
)
throw new NullReferenceException("Missing StorageProvider instance.");
var folder = await provider.OpenFolderPickerAsync(
new FolderPickerOpenOptions() { Title = "Open Text File", AllowMultiple = false }
);
return folder?.Count >= 1 ? folder[0] : null;
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
namespace DotNetSolutionTools.App.ViewModels;
public partial class ViewModelBase : ObservableObject
{
protected ViewModelBase()
{
ErrorMessages = new ObservableCollection<string>();
}
[ObservableProperty]
private ObservableCollection<string>? _errorMessages;
}

View File

@@ -0,0 +1,30 @@
<Window 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:viewModels="clr-namespace:DotNetSolutionTools.App.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="DotNetSolutionTools.App.Views.MainWindow"
x:DataType="viewModels:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="FileOps">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<viewModels:MainWindowViewModel />
</Design.DataContext>
<Panel>
<StackPanel>
<TextBlock>Welcome to Avalonia!</TextBlock>
<Button Command="{Binding LoadSolutionFolderCommand}" >Select Solution Folder</Button>
<Button Command="{Binding LoadSolutionFileCommand}">Select Solution File</Button>
<Button Command="{Binding ExecuteParityCheckerCommand}">Check Solution Parity</Button>
<Button Command="{Binding FormatCsProjFileCommand}">Format CSharp Project File</Button>
<TextBlock Name="SolutionFilePath" Text="{Binding SolutionFilePath}" />
<TextBlock Name="SolutionFolderPath" Text="{Binding SolutionFolderPath}" />
<ListBox Name="Results" ItemsSource="{Binding ParityResults}"/>
<ListBox ItemsSource="{Binding ErrorMessages}"/>
</StackPanel>
</Panel>
</Window>

View File

@@ -0,0 +1,13 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using DotNetSolutionTools.App.ViewModels;
namespace DotNetSolutionTools.App.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,18 @@
<?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 embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="SolutionParityChecker.App.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>