using System.Reactive.Disposables; using Avalonia; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.ReactiveUI; using Avalonia.VisualTree; using ReactiveUI; namespace v2rayN.Desktop.Views; public partial class ProfilesSelectWindow : ReactiveWindow { private static Config _config; public Task ProfileItem => GetProfileItem(); public Task?> ProfileItems => GetProfileItems(); private bool _allowMultiSelect = false; public ProfilesSelectWindow() { InitializeComponent(); _config = AppManager.Instance.Config; btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click; txtServerFilter.KeyDown += TxtServerFilter_KeyDown; lstProfiles.KeyDown += LstProfiles_KeyDown; lstProfiles.SelectionChanged += LstProfiles_SelectionChanged; lstProfiles.LoadingRow += LstProfiles_LoadingRow; lstProfiles.Sorting += LstProfiles_Sorting; lstProfiles.DoubleTapped += LstProfiles_DoubleTapped; ViewModel = new ProfilesSelectViewModel(UpdateViewHandler); DataContext = ViewModel; this.WhenActivated(disposables => { this.OneWayBind(ViewModel, vm => vm.ProfileItems, v => v.lstProfiles.ItemsSource).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedProfile, v => v.lstProfiles.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSub, v => v.lstGroup.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.ServerFilter, v => v.txtServerFilter.Text).DisposeWith(disposables); }); btnCancel.Click += (s, e) => Close(false); } public void AllowMultiSelect(bool allow) { _allowMultiSelect = allow; if (allow) { lstProfiles.SelectionMode = DataGridSelectionMode.Extended; lstProfiles.SelectedItems.Clear(); } else { lstProfiles.SelectionMode = DataGridSelectionMode.Single; if (lstProfiles.SelectedItems.Count > 0) { var first = lstProfiles.SelectedItems[0]; lstProfiles.SelectedItems.Clear(); lstProfiles.SelectedItem = first; } } } // Expose ConfigType filter controls to callers public void SetConfigTypeFilter(IEnumerable types, bool exclude = false) => ViewModel?.SetConfigTypeFilter(types, exclude); private async Task UpdateViewHandler(EViewAction action, object? obj) { switch (action) { case EViewAction.CloseWindow: Close(true); break; } return await Task.FromResult(true); } private void LstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e) { if (ViewModel != null) { ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast().ToList(); } } private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e) { e.Row.Header = $" {e.Row.Index + 1}"; } private void LstProfiles_DoubleTapped(object? sender, TappedEventArgs e) { // 忽略表头区域的双击 if (e.Source is Control src) { if (src.FindAncestorOfType() != null) { e.Handled = true; return; } // 仅当在数据行或其子元素上双击时才触发选择 if (src.FindAncestorOfType() != null) { ViewModel?.SelectFinish(); e.Handled = true; } } } private void LstProfiles_Sorting(object? sender, DataGridColumnEventArgs e) { // 自定义排序,防止默认行为导致误触发 e.Handled = true; if (ViewModel != null && e.Column?.Tag?.ToString() != null) { ViewModel.SortServer(e.Column.Tag.ToString()); } } private void LstProfiles_KeyDown(object? sender, KeyEventArgs e) { if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta) { if (e.Key == Key.A) { if (_allowMultiSelect) { lstProfiles.SelectAll(); } e.Handled = true; } } else { if (e.Key is Key.Enter or Key.Return) { ViewModel?.SelectFinish(); e.Handled = true; } } } private void BtnAutofitColumnWidth_Click(object? sender, RoutedEventArgs e) { AutofitColumnWidth(); } private void AutofitColumnWidth() { try { foreach (var col in lstProfiles.Columns) { col.Width = new DataGridLength(1, DataGridLengthUnitType.Auto); } } catch { } } private void TxtServerFilter_KeyDown(object? sender, KeyEventArgs e) { if (e.Key is Key.Enter or Key.Return) { ViewModel?.RefreshServers(); } } public async Task GetProfileItem() { var item = await ViewModel?.GetProfileItem(); return item; } public async Task?> GetProfileItems() { var item = await ViewModel?.GetProfileItems(); return item; } private void BtnSave_Click(object sender, RoutedEventArgs e) { // Trigger selection finalize when Confirm is clicked ViewModel?.SelectFinish(); } }