using CommunityToolkit.Mvvm.ComponentModel; using FluidExplorer.Navigation; using FluidExplorer.Services; using FluidExplorer.Services.FileSystem; using FluidExplorer.Services.ItemVisuals; using FluidExplorer.Services.Operations; using FluidExplorer.Services.Search; using Microsoft.UI.Dispatching; using PathHelper = FluidExplorer.Services.FileSystem.PathHelper; namespace FluidExplorer.ViewModels; /// 一个标签页:包含主窗格,可选第二窗格(双窗格模式,搬文件不用来回切)。 public sealed partial class ExplorerTabViewModel : ObservableObject { private readonly IFileSystemService _fs; private readonly SearchService _search; private readonly IFileOperationService _operations; private readonly ItemVisualService _visuals; private readonly IFileClipboard _clipboard; private readonly AppSettings _settings; private readonly DispatcherQueue _ui; [ObservableProperty] private bool _isDualPane; [ObservableProperty] private bool _isActivePaneSecondary; [ObservableProperty] private string _header = "新标签页"; [ObservableProperty] private string _glyph = "\uE8B7"; public ExplorerTabViewModel( IFileSystemService fs, SearchService search, IFileOperationService operations, ItemVisualService visuals, IFileClipboard clipboard, AppSettings settings, DispatcherQueue ui, NavigationLocation start) { _fs = fs; _search = search; _operations = operations; _visuals = visuals; _clipboard = clipboard; _settings = settings; _ui = ui; Primary = new ExplorerPaneViewModel(fs, search, operations, visuals, clipboard, settings, ui); Primary.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(ExplorerPaneViewModel.Title)) UpdateHeader(); }; Primary.SettingsChanged += (_, _) => UpdateHeader(); _ = Primary.NavigateAsync(start); UpdateHeader(); } public ExplorerPaneViewModel Primary { get; } [ObservableProperty] private ExplorerPaneViewModel? _secondary; public ExplorerPaneViewModel ActivePane => IsDualPane && IsActivePaneSecondary && Secondary is not null ? Secondary : Primary; public ExplorerPaneViewModel EnsureSecondary() { if (Secondary is not null) return Secondary; var pane = new ExplorerPaneViewModel(_fs, _search, _operations, _visuals, _clipboard, _settings, _ui) { ShowSidebar = false }; pane.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(ExplorerPaneViewModel.Title)) UpdateHeader(); }; Secondary = pane; return pane; } public void ToggleDualPane() { if (IsDualPane) { IsDualPane = false; IsActivePaneSecondary = false; return; } var secondary = EnsureSecondary(); if (string.IsNullOrEmpty(secondary.CurrentPath) || secondary.CurrentPath.StartsWith("::", StringComparison.Ordinal)) { // 第二个窗格默认停在与主窗格同级的目录,便于对拖 var parent = PathHelper.GetParent(Primary.CurrentPath); _ = secondary.NavigateAsync(NavigationLocation.FromPath( Directory.Exists(parent) ? parent : Primary.CurrentPath)); } IsDualPane = true; } private void UpdateHeader() { Header = Primary.IsSearchActive && !string.IsNullOrWhiteSpace(Primary.SearchText) ? $"搜索:{Primary.SearchText}" : Primary.Title; Glyph = Primary.Glyph; } public void Dispose() { Primary.Dispose(); Secondary?.Dispose(); } }