diff --git a/PCL2.Neo/App.axaml.cs b/PCL2.Neo/App.axaml.cs index 355c112b..f6f5c083 100644 --- a/PCL2.Neo/App.axaml.cs +++ b/PCL2.Neo/App.axaml.cs @@ -1,14 +1,16 @@ -using System; using System.Linq; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Data.Core; using Avalonia.Data.Core.Plugins; using Avalonia.Markup.Xaml; -using PCL2.Neo.Helpers; -using PCL2.Neo.Utils; +using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using PCL2.Neo.Services; using PCL2.Neo.ViewModels; +using PCL2.Neo.ViewModels.Download; +using PCL2.Neo.ViewModels.Home; using PCL2.Neo.Views; +using System; namespace PCL2.Neo { @@ -19,14 +21,33 @@ public override void Initialize() AvaloniaXamlLoader.Load(this); } + private static IServiceProvider ConfigureServices() => new ServiceCollection() + .AddTransient() + + .AddTransient() + .AddTransient() + + .AddTransient() + .AddTransient() + .AddTransient() + + .AddSingleton(s => new NavigationService(s)) + .BuildServiceProvider(); + public override void OnFrameworkInitializationCompleted() { + Ioc.Default.ConfigureServices(ConfigureServices()); + + var vm = Ioc.Default.GetRequiredService(); if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { // Avoid duplicate validations from both Avalonia and the CommunityToolkit. // More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins DisableAvaloniaDataAnnotationValidation(); - desktop.MainWindow = new MainWindow(); + desktop.MainWindow = new MainWindow + { + DataContext = vm + }; } base.OnFrameworkInitializationCompleted(); diff --git a/PCL2.Neo/Attributes.cs b/PCL2.Neo/Attributes.cs new file mode 100644 index 00000000..852b2850 --- /dev/null +++ b/PCL2.Neo/Attributes.cs @@ -0,0 +1,15 @@ +using System; + +namespace PCL2.Neo; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +public class SubViewModelOfAttribute(Type parentViewModel) : Attribute +{ + public Type ParentViewModel { get; } = parentViewModel; +} + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +public class DefaultSubViewModelAttribute(Type subViewModel) : Attribute +{ + public Type SubViewModel { get; } = subViewModel; +} \ No newline at end of file diff --git a/PCL2.Neo/PCL2.Neo.csproj b/PCL2.Neo/PCL2.Neo.csproj index f8a87052..fb82ff64 100644 --- a/PCL2.Neo/PCL2.Neo.csproj +++ b/PCL2.Neo/PCL2.Neo.csproj @@ -35,8 +35,9 @@ All - + + @@ -46,4 +47,22 @@ + + + + HomeLeftView.axaml + + + HomeRightView.axaml + Code + + + DownloadRightView.axaml + Code + + + DownloadModView.axaml + Code + + diff --git a/PCL2.Neo/Services/NavigationService.cs b/PCL2.Neo/Services/NavigationService.cs new file mode 100644 index 00000000..d68cc854 --- /dev/null +++ b/PCL2.Neo/Services/NavigationService.cs @@ -0,0 +1,83 @@ +using Microsoft.Extensions.DependencyInjection; +using PCL2.Neo.ViewModels; +using System; +using System.Reflection; + +namespace PCL2.Neo.Services; + +public class NavigationService +{ + public IServiceProvider ServiceProvider { get; init; } + + public event Action? CurrentViewModelChanged; + public event Action? CurrentSubViewModelChanged; + + private ViewModelBase? _currentViewModel; + public ViewModelBase? CurrentViewModel + { + get => _currentViewModel; + protected set + { + if (value == _currentViewModel) + return; + _currentViewModel = value; + CurrentViewModelChanged?.Invoke(value); + } + } + + private ViewModelBase? _currentSubViewModel; + public ViewModelBase? CurrentSubViewModel + { + get => _currentSubViewModel; + protected set + { + if (value == _currentSubViewModel) + return; + _currentSubViewModel = value; + CurrentSubViewModelChanged?.Invoke(value); + } + } + + public NavigationService(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public virtual T Goto() where T : ViewModelBase + { + if (typeof(T).GetCustomAttribute() is { } dsvm) + { + var vm = CurrentViewModel as T; + if (vm?.GetType() != typeof(T)) + { + vm = ServiceProvider.GetRequiredService(); + CurrentViewModel = vm; + } + if (CurrentSubViewModel?.GetType() != dsvm.SubViewModel) + CurrentSubViewModel = ServiceProvider.GetRequiredService(dsvm.SubViewModel) as ViewModelBase; + return vm; + } + + if (typeof(T).GetCustomAttribute() is { } svmo) + { + var subVm = CurrentSubViewModel as T; + if (CurrentViewModel?.GetType() != svmo.ParentViewModel) + CurrentViewModel = ServiceProvider.GetRequiredService(svmo.ParentViewModel) as ViewModelBase; + if (subVm?.GetType() != typeof(T)) + { + subVm = ServiceProvider.GetRequiredService(); + CurrentSubViewModel = subVm; + } + return subVm; + } + + var targetVm = CurrentViewModel?.GetType() != typeof(T) || CurrentSubViewModel?.GetType() != typeof(T) + ? ServiceProvider.GetRequiredService() + : (T)CurrentViewModel; + if (CurrentViewModel?.GetType() != typeof(T)) + CurrentViewModel = targetVm; + if (CurrentSubViewModel?.GetType() != typeof(T)) + CurrentSubViewModel = targetVm; + return targetVm; + } +} \ No newline at end of file diff --git a/PCL2.Neo/ViewLocator.cs b/PCL2.Neo/ViewLocator.cs index 2fbc639e..9aecab0b 100644 --- a/PCL2.Neo/ViewLocator.cs +++ b/PCL2.Neo/ViewLocator.cs @@ -3,28 +3,28 @@ using Avalonia.Controls.Templates; using PCL2.Neo.ViewModels; -namespace PCL2.Neo +namespace PCL2.Neo; + +public class ViewLocator : IDataTemplate { - public class ViewLocator : IDataTemplate + public Control? Build(object? param) { - public Control? Build(object? param) - { - if (param is null) - return null; + if (param is null) + return null; - var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); - var type = Type.GetType(name); + var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); + var type = Type.GetType(name); - if (type != null) - { - return (Control)Activator.CreateInstance(type)!; - } - - return new TextBlock { Text = "Not Found: " + name }; - } - public bool Match(object? data) + if (type != null) { - return data is ViewModelBase; + return (Control)Activator.CreateInstance(type)!; } + + return new TextBlock { Text = "Not Found: " + name }; + } + + public bool Match(object? data) + { + return data is ViewModelBase; } -} +} \ No newline at end of file diff --git a/PCL2.Neo/ViewModels/Download/DownloadGameViewModel.cs b/PCL2.Neo/ViewModels/Download/DownloadGameViewModel.cs new file mode 100644 index 00000000..90522970 --- /dev/null +++ b/PCL2.Neo/ViewModels/Download/DownloadGameViewModel.cs @@ -0,0 +1,7 @@ +namespace PCL2.Neo.ViewModels.Download; + +[SubViewModelOf(typeof(DownloadViewModel))] +public class DownloadGameViewModel : ViewModelBase +{ + +} \ No newline at end of file diff --git a/PCL2.Neo/ViewModels/Download/DownloadModViewModel.cs b/PCL2.Neo/ViewModels/Download/DownloadModViewModel.cs new file mode 100644 index 00000000..7f724923 --- /dev/null +++ b/PCL2.Neo/ViewModels/Download/DownloadModViewModel.cs @@ -0,0 +1,7 @@ +namespace PCL2.Neo.ViewModels.Download; + +[SubViewModelOf(typeof(DownloadViewModel))] +public class DownloadModViewModel : ViewModelBase +{ + +} \ No newline at end of file diff --git a/PCL2.Neo/ViewModels/DownloadViewModel.cs b/PCL2.Neo/ViewModels/DownloadViewModel.cs new file mode 100644 index 00000000..e687a306 --- /dev/null +++ b/PCL2.Neo/ViewModels/DownloadViewModel.cs @@ -0,0 +1,44 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using PCL2.Neo.Services; +using PCL2.Neo.ViewModels.Download; + +namespace PCL2.Neo.ViewModels; + +[DefaultSubViewModel(typeof(DownloadGameViewModel))] +public partial class DownloadViewModel : ViewModelBase +{ + public NavigationService NavigationService { get; } + + [ObservableProperty] + private string _message = "I am from DownloadViewModel"; + + public DownloadViewModel(NavigationService navigationService) + { + NavigationService = navigationService; + } + + [RelayCommand] + private void NavigateToDownloadGame() + { + this.NavigationService.Goto(); + } + + [RelayCommand] + private void NavigateToDownloadMod() + { + this.NavigationService.Goto(); + } + + [RelayCommand] + private void Btn_Test1() + { + Message = "I am from DownloadViewModel Test1"; + } + + [RelayCommand] + private void Btn_Test2() + { + Message = "I am from DownloadViewModel Test2"; + } +} \ No newline at end of file diff --git a/PCL2.Neo/ViewModels/Home/HomeSubViewModel.cs b/PCL2.Neo/ViewModels/Home/HomeSubViewModel.cs new file mode 100644 index 00000000..96d2c784 --- /dev/null +++ b/PCL2.Neo/ViewModels/Home/HomeSubViewModel.cs @@ -0,0 +1,22 @@ +using CommunityToolkit.Mvvm.Input; +using PCL2.Neo.Services; +using PCL2.Neo.ViewModels.Download; + +namespace PCL2.Neo.ViewModels.Home; + +[SubViewModelOf(typeof(HomeViewModel))] +public partial class HomeSubViewModel : ViewModelBase +{ + public NavigationService NavigationService { get; } + + public HomeSubViewModel(NavigationService navigationService) + { + this.NavigationService = navigationService; + } + + [RelayCommand] + private void NavigateToDownloadMod() + { + this.NavigationService.Goto(); + } +} \ No newline at end of file diff --git a/PCL2.Neo/ViewModels/HomeViewModel.cs b/PCL2.Neo/ViewModels/HomeViewModel.cs new file mode 100644 index 00000000..2a2e23c0 --- /dev/null +++ b/PCL2.Neo/ViewModels/HomeViewModel.cs @@ -0,0 +1,9 @@ +using PCL2.Neo.ViewModels.Home; + +namespace PCL2.Neo.ViewModels; + +[DefaultSubViewModel(typeof(HomeSubViewModel))] +public class HomeViewModel : ViewModelBase +{ + +} \ No newline at end of file diff --git a/PCL2.Neo/ViewModels/MainWindowViewModel.cs b/PCL2.Neo/ViewModels/MainWindowViewModel.cs index 7b121870..f252a6d8 100644 --- a/PCL2.Neo/ViewModels/MainWindowViewModel.cs +++ b/PCL2.Neo/ViewModels/MainWindowViewModel.cs @@ -1,22 +1,74 @@ using Avalonia.Controls; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using PCL2.Neo.Controls.MyMsg; +using PCL2.Neo.Services; using PCL2.Neo.Helpers; using System.Threading.Tasks; + namespace PCL2.Neo.ViewModels { public partial class MainWindowViewModel : ViewModelBase { private Window? _window; + public NavigationService NavigationService { get; } + + // quite shitty, maybe consider using enum and converters + [ObservableProperty] private bool _isNavBtn1Checked = true; + [ObservableProperty] private bool _isNavBtn2Checked; + [ObservableProperty] private bool _isNavBtn3Checked; + [ObservableProperty] private bool _isNavBtn4Checked; + [ObservableProperty] private bool _isNavBtn5Checked; + + [ObservableProperty] + private ViewModelBase? _currentViewModel; + [ObservableProperty] + private ViewModelBase? _currentSubViewModel; // 为了设计时的 DataContext public MainWindowViewModel() { + throw new System.NotImplementedException(); } public MainWindowViewModel(Window window) { this._window = window; } + public MainWindowViewModel(NavigationService navigationService) + { + this.NavigationService = navigationService; + this.NavigationService.CurrentViewModelChanged += x => + { + CurrentViewModel = x; + switch (x) + { + case HomeViewModel: + IsNavBtn1Checked = true; + break; + case DownloadViewModel: + IsNavBtn2Checked = true; + break; + } + }; + this.NavigationService.CurrentSubViewModelChanged += x => + { + CurrentSubViewModel = x; + }; + this.NavigationService.Goto(); + } + + [RelayCommand] + public void NavigateToHome() + { + this.NavigationService.Goto(); + } + + [RelayCommand] + public void NavigateToDownload() + { + this.NavigationService.Goto(); + } public void Close() { @@ -29,7 +81,7 @@ public void Minimize() _window.WindowState = WindowState.Minimized; } - public void ShowMessageBox((MessageBoxParam, TaskCompletionSource) messageBoxParam) + public void ShowMessageBox(IMessageBox messageBox) { } diff --git a/PCL2.Neo/ViewModels/ViewModelBase.cs b/PCL2.Neo/ViewModels/ViewModelBase.cs index 5ef648a5..515c3506 100644 --- a/PCL2.Neo/ViewModels/ViewModelBase.cs +++ b/PCL2.Neo/ViewModels/ViewModelBase.cs @@ -1,9 +1,8 @@ using CommunityToolkit.Mvvm.ComponentModel; -namespace PCL2.Neo.ViewModels +namespace PCL2.Neo.ViewModels; + +public partial class ViewModelBase : ObservableObject { - public class ViewModelBase : ObservableObject - { - } -} +} \ No newline at end of file diff --git a/PCL2.Neo/Views/Download/DownloadGameView.axaml b/PCL2.Neo/Views/Download/DownloadGameView.axaml new file mode 100644 index 00000000..da02522c --- /dev/null +++ b/PCL2.Neo/Views/Download/DownloadGameView.axaml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/PCL2.Neo/Views/Download/DownloadGameView.axaml.cs b/PCL2.Neo/Views/Download/DownloadGameView.axaml.cs new file mode 100644 index 00000000..4c66f950 --- /dev/null +++ b/PCL2.Neo/Views/Download/DownloadGameView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace PCL2.Neo.Views.Download; + +public partial class DownloadGameView : UserControl +{ + public DownloadGameView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/PCL2.Neo/Views/Download/DownloadModView.axaml b/PCL2.Neo/Views/Download/DownloadModView.axaml new file mode 100644 index 00000000..1afd2255 --- /dev/null +++ b/PCL2.Neo/Views/Download/DownloadModView.axaml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/PCL2.Neo/Views/Download/DownloadModView.axaml.cs b/PCL2.Neo/Views/Download/DownloadModView.axaml.cs new file mode 100644 index 00000000..ae693946 --- /dev/null +++ b/PCL2.Neo/Views/Download/DownloadModView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace PCL2.Neo.Views.Download; + +public partial class DownloadModView : UserControl +{ + public DownloadModView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/PCL2.Neo/Views/DownloadView.axaml b/PCL2.Neo/Views/DownloadView.axaml new file mode 100644 index 00000000..cef8a615 --- /dev/null +++ b/PCL2.Neo/Views/DownloadView.axaml @@ -0,0 +1,40 @@ + + + + + + + + + + + diff --git a/PCL2.Neo/Views/DownloadView.axaml.cs b/PCL2.Neo/Views/DownloadView.axaml.cs new file mode 100644 index 00000000..b1eb0768 --- /dev/null +++ b/PCL2.Neo/Views/DownloadView.axaml.cs @@ -0,0 +1,14 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace PCL2.Neo.Views +{ + public partial class DownloadView : UserControl + { + public DownloadView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/PCL2.Neo/Views/Home/HomeSubView.axaml b/PCL2.Neo/Views/Home/HomeSubView.axaml new file mode 100644 index 00000000..dbb67cc9 --- /dev/null +++ b/PCL2.Neo/Views/Home/HomeSubView.axaml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PCL2.Neo/Views/Home/HomeSubView.axaml.cs b/PCL2.Neo/Views/Home/HomeSubView.axaml.cs new file mode 100644 index 00000000..e48a6a4f --- /dev/null +++ b/PCL2.Neo/Views/Home/HomeSubView.axaml.cs @@ -0,0 +1,57 @@ +using Avalonia.Controls; +using Avalonia.Interactivity; +using PCL2.Neo.Controls; +using PCL2.Neo.Models.Minecraft.Java; +using System; +using System.Linq; + +namespace PCL2.Neo.Views.Home; + +public partial class HomeSubView : UserControl +{ + public HomeSubView() + { + InitializeComponent(); + } + + private void Button_OnClick(object? sender, RoutedEventArgs e) + { + this.TestLoading.State = MyLoading.LoadingState.Loading; + } + + private void Button2_OnClick(object? sender, RoutedEventArgs e) + { + this.TestLoading.State = MyLoading.LoadingState.Error; + } + + private async void Search_Java_Button(object? sender, RoutedEventArgs e) + { + try + { + var javas = await Java.SearchJava(); + Console.WriteLine($"找到 {javas.Count()} 个Java环境:"); + + foreach (var java in javas) + { + try + { + Console.WriteLine("----------------------"); + Console.WriteLine($"路径: {java.DirectoryPath}"); + var version = java.Version; + Console.WriteLine($"版本: Java {version}"); + Console.WriteLine($"位数: {(java.Is64Bit ? "64位" : "32位")}"); + Console.WriteLine($"类型: {(java.IsJre ? "JRE" : "JDK")}"); + Console.WriteLine($"可用: {java.Compability}"); + } + catch (Exception ex) + { + Console.WriteLine($"处理Java信息时出错: {ex.Message}"); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"搜索失败: {ex.Message}"); + } + } +} \ No newline at end of file diff --git a/PCL2.Neo/Views/HomeView.axaml b/PCL2.Neo/Views/HomeView.axaml new file mode 100644 index 00000000..ba939041 --- /dev/null +++ b/PCL2.Neo/Views/HomeView.axaml @@ -0,0 +1,13 @@ + + Welcome to Avalonia!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + diff --git a/PCL2.Neo/Views/HomeView.axaml.cs b/PCL2.Neo/Views/HomeView.axaml.cs new file mode 100644 index 00000000..d5c929cf --- /dev/null +++ b/PCL2.Neo/Views/HomeView.axaml.cs @@ -0,0 +1,14 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace PCL2.Neo.Views +{ + public partial class HomeView : UserControl + { + public HomeView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/PCL2.Neo/Views/MainWindow.axaml b/PCL2.Neo/Views/MainWindow.axaml index 7bd1abe6..7bfaa599 100644 --- a/PCL2.Neo/Views/MainWindow.axaml +++ b/PCL2.Neo/Views/MainWindow.axaml @@ -17,7 +17,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:pc="using:PCL2.Neo.Controls" - xmlns:vm="clr-namespace:PCL2.Neo.ViewModels" + xmlns:vm="using:PCL2.Neo.ViewModels" + xmlns:local="using:PCL2.Neo" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + ZIndex="3"> + ZIndex="3"> + Text="{DynamicResource LangTitleHome}" + Command="{Binding NavigateToHome}" /> + Text="{DynamicResource LangTitleDownload}" + Command="{Binding NavigateToDownload}" /> - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + ZIndex="10" /> diff --git a/PCL2.Neo/Views/MainWindow.axaml.cs b/PCL2.Neo/Views/MainWindow.axaml.cs index 965c1715..8704f8a1 100644 --- a/PCL2.Neo/Views/MainWindow.axaml.cs +++ b/PCL2.Neo/Views/MainWindow.axaml.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Animation.Easings; using Avalonia.Controls; +using Avalonia.Controls.Presenters; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media; @@ -10,12 +11,12 @@ using PCL2.Neo.Animations.Easings; using PCL2.Neo.Controls; using PCL2.Neo.Helpers; -using PCL2.Neo.Models.Minecraft.Java; using System; using System.Linq; using System.Numerics; using System.Runtime.InteropServices; using System.Threading.Tasks; +using CubicEaseOut = Avalonia.Animation.Easings.CubicEaseOut; namespace PCL2.Neo.Views; @@ -55,14 +56,37 @@ public MainWindow() BtnTitleMin.Click += (_, _) => WindowState = WindowState.Minimized; - GridRoot.Opacity = 0; // 在此处初始化透明度,不然将闪现 - this.Loaded += (_, _) => AnimationIn(); - } - private void OnNavPointerPressed(object? sender, PointerPressedEventArgs e) - { + LeftNavigationControl.Loaded += (_, _) => + { + LeftNavigationControlBorder.Width = LeftNavigationControl.Presenter!.Child?.Width ?? 0d; + AnimationHelper? lastAnimation = null; + LeftNavigationControl.Presenter!.PropertyChanged += async (_, e) => + { + if (e.Property != ContentPresenter.ChildProperty) + return; + var oldValue = e.OldValue as Control; + var newValue = e.NewValue as Control; + lastAnimation?.CancelAndClear(); + var previousScaleTransform = + (LeftNavigationControlBorder.RenderTransform as TransformGroup)?.Children + .FirstOrDefault(x => x is ScaleTransform) as ScaleTransform; + var previousScaleX = previousScaleTransform?.ScaleX ?? 1d; + LeftNavigationControlBorder.Width = LeftNavigationControl.Presenter!.Child?.Width ?? 0d; + var scale = oldValue?.Width / newValue?.Width * previousScaleX ?? 1d; + lastAnimation = new AnimationHelper( + [ + new ScaleTransformScaleXAnimation(LeftNavigationControlBorder, TimeSpan.FromMilliseconds(300), scale, + 1d, new CubicEaseOut()) + ]); + await lastAnimation.RunAsync(); + }; + }; - } + GridRoot.Opacity = 0; // 在此处初始化透明度,不然将闪现 + this.Loaded += (_, _) => AnimationIn(); + } + private void SetupSide(string name, StandardCursorType cursor, WindowEdge edge) { var ctl = this.Get(name); @@ -182,45 +206,4 @@ private void AnimationOut() mainWindowCompositionVisual.StartAnimationGroup(animationGroup); } } - - private void Button_OnClick(object? sender, RoutedEventArgs e) - { - this.TestLoading.State = MyLoading.LoadingState.Loading; - } - - private void Button2_OnClick(object? sender, RoutedEventArgs e) - { - this.TestLoading.State = MyLoading.LoadingState.Error; - } - - private async void Search_Java_Button(object? sender, RoutedEventArgs e) - { - try - { - var javas = await Java.SearchJava(); - Console.WriteLine($"找到 {javas.Count()} 个Java环境:"); - - foreach (var java in javas) - { - try - { - Console.WriteLine("----------------------"); - Console.WriteLine($"路径: {java.DirectoryPath}"); - var version = java.Version; - Console.WriteLine($"版本: Java {version}"); - Console.WriteLine($"位数: {(java.Is64Bit ? "64位" : "32位")}"); - Console.WriteLine($"类型: {(java.IsJre ? "JRE" : "JDK")}"); - Console.WriteLine($"可用: {java.Compability}"); - } - catch (Exception ex) - { - Console.WriteLine($"处理Java信息时出错: {ex.Message}"); - } - } - } - catch (Exception ex) - { - Console.WriteLine($"搜索失败: {ex.Message}"); - } - } } \ No newline at end of file