feat: 同时启动多个模拟器时使用自动检测连接时提供弹窗选择 (#16020)

feat: 同时启动多个模拟器时使用自动检测连接时提供弹窗选择


https://github.com/user-attachments/assets/0b424e4d-6704-4d63-84dc-64916df6220b

## Summary by Sourcery

添加通用的项目选择对话框,并使用它在自动检测期间处理多个已检测到的模拟器和连接地址。

New Features:
- 引入可复用的项目选择对话框和视图模型,可以显示带有可自定义标题和提示语的项目列表,并返回所选项目。
- 当检测到多个模拟器或多个 ADB 路径时,允许用户选择要连接的模拟器实例。
- 当检测到多个非默认的 ADB 连接地址时,允许用户选择要使用的连接地址。

Bug Fixes:
- 当发现多个候选项时,通过明确要求用户进行选择,防止产生含糊不清或错误的模拟器/ADB 选择。
- 当不存在有效目录时,将已配置路径初始化为空,避免强制使用硬编码的默认模拟器安装路径。
- 确保选择对话框始终在 UI 线程调度器上创建和显示,以避免潜在的线程问题。

Enhancements:
- 优化模拟器检测逻辑,以同时跟踪模拟器名称和解析后的 ADB 路径,对结果去重,并在选择界面中展示这些信息。
- 使用通用项目选择对话框替换特定于模拟器路径的对话框,并简化相关视图模型的职责。
- 通过可在不同选择场景中复用的通用选择与提示字符串,改进本地化支持。

<details>
<summary>Original summary in English</summary>

## Summary by Sourcery

Add generic item selection dialog and use it to handle multiple detected
emulators and connection addresses during auto-detection.

New Features:
- Introduce a reusable item selection dialog and view model that can
display a list of items with customizable title and prompt and return
the selected item.
- Allow users to choose which emulator instance to connect to when
multiple emulators or ADB paths are detected.
- Allow users to choose which connection address to use when multiple
non-default ADB addresses are detected.

Bug Fixes:
- Prevent ambiguous or incorrect emulator/ADB selection by explicitly
requiring a user choice when multiple candidates are found.
- Avoid forcing hard-coded default emulator installation paths by
initializing configured paths as empty when no valid directory exists.
- Ensure selection dialogs are always created and shown on the UI thread
dispatcher to avoid potential threading issues.

Enhancements:
- Refine emulator detection to track both emulator name and resolved ADB
path, deduplicate results, and surface this information in the selection
UI.
- Replace the emulator-path-specific dialog with a generic item
selection dialog and simplify related view model responsibilities.
- Improve localization support with generic selection and prompt strings
that can be reused across different selection scenarios.

</details>
This commit is contained in:
uye
2026-03-19 22:56:50 +08:00
committed by GitHub
parent 42c0d75e89
commit ae0a3c4871
11 changed files with 252 additions and 113 deletions

View File

@@ -11,6 +11,8 @@
// but WITHOUT ANY WARRANTY
// </copyright>
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -27,6 +29,17 @@ public class WinAdapter
{
private static readonly ILogger _logger = Log.ForContext<WinAdapter>();
public sealed class DetectedEmulatorInfo(string emulatorName, string? adbPath)
{
public string EmulatorName { get; } = emulatorName;
public string? AdbPath { get; } = adbPath;
public string SelectionDisplayText => string.IsNullOrEmpty(AdbPath)
? EmulatorName
: $"{EmulatorName} ({AdbPath})";
}
private static readonly Dictionary<string, string> _emulatorIdDict = new()
{
{ "HD-Player", "BlueStacks" },
@@ -59,16 +72,15 @@ public class WinAdapter
{ "XYAZ", [@".\adb.exe"] },
};
private readonly Dictionary<string, string> _adbAbsolutePathDict = new();
/// <summary>
/// Refreshes emulator information.
/// </summary>
/// <returns>The list of emulators.</returns>
public List<string> RefreshEmulatorsInfo()
/// <returns>The detected emulator infos.</returns>
public List<DetectedEmulatorInfo> RefreshEmulatorsInfo()
{
var allProcess = Process.GetProcesses();
var emulators = new List<string>();
var emulators = new List<DetectedEmulatorInfo>();
var detectedEmulators = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var process in allProcess)
{
if (!_emulatorIdDict.TryGetValue(process.ProcessName, out var emulatorId))
@@ -76,13 +88,11 @@ public class WinAdapter
continue;
}
emulators.Add(emulatorId);
var processPath = process.MainModule?.FileName;
foreach (string adbPath in _adbRelativePathDict[emulatorId]
.Select(path => Path.GetDirectoryName(processPath) + "\\" + path)
.Where(File.Exists))
var adbPath = GetAdbPathByProcessPath(process.MainModule?.FileName, emulatorId);
var detectionKey = $"{emulatorId}\n{adbPath}";
if (detectedEmulators.Add(detectionKey))
{
_adbAbsolutePathDict[emulatorId] = adbPath;
emulators.Add(new DetectedEmulatorInfo(emulatorId, adbPath));
}
}
@@ -90,13 +100,22 @@ public class WinAdapter
}
/// <summary>
/// Gets ADB path by emulator name.
/// Gets the preferred ADB path for a process.
/// </summary>
/// <param name="processPath">The emulator executable path.</param>
/// <param name="emulatorName">The name of the emulator.</param>
/// <returns>The ADB path of the emulator.</returns>
public string GetAdbPathByEmulatorName(string emulatorName)
private static string? GetAdbPathByProcessPath(string? processPath, string emulatorName)
{
return _adbAbsolutePathDict.GetValueOrDefault(emulatorName);
var processDirectory = Path.GetDirectoryName(processPath);
if (string.IsNullOrEmpty(processDirectory))
{
return null;
}
return _adbRelativePathDict[emulatorName]
.Select(path => Path.GetFullPath(Path.Combine(processDirectory, path)))
.FirstOrDefault(File.Exists);
}
/// <summary>

View File

@@ -1843,9 +1843,16 @@ If you want to run multiple MAA at the same time, please copy the whole MAA and
<system:String x:Key="BadModules.ResetSuccess">Hardware rendering mode has been restored. Restart MAA to apply changes. Restart now?</system:String>
<!-- !BadModules -->
<!-- EmulatorPathSelection -->
<!-- ItemSelection -->
<system:String x:Key="SelectItem">Select Item</system:String>
<system:String x:Key="SelectEmulatorPath">Select Emulator Path</system:String>
<system:String x:Key="SelectEmulator">Select Emulator</system:String>
<system:String x:Key="SelectConnectionAddress">Select Connection Address</system:String>
<system:String x:Key="MultipleEmulatorsDetected">Multiple emulator installation paths detected, please select the path you want to use:</system:String>
<system:String x:Key="MultipleEmulatorsDetectedForConnection">Multiple emulators detected, please select the emulator you want to connect to:</system:String>
<system:String x:Key="MultipleAddressesDetected">Multiple connection addresses detected, please select the address you want to use:</system:String>
<system:String x:Key="PleaseSelectPath">Please select a path</system:String>
<!-- !EmulatorPathSelection -->
<system:String x:Key="PleaseSelectItem">Please select an item</system:String>
<system:String x:Key="EmulatorSelectionCancelled">Emulator selection cancelled</system:String>
<!-- !ItemSelection -->
</ResourceDictionary>

View File

@@ -1844,9 +1844,16 @@ MAA を複数開くには、新しい MAA を他のフォルダにコピーし
<system:String x:Key="BadModules.ResetSuccess">ハードウェアレンダリングモードに戻しました。変更を適用するには MAA を再起動する必要があります。今すぐ再起動しますか?</system:String>
<!-- !BadModules -->
<!-- EmulatorPathSelection -->
<!-- ItemSelection -->
<system:String x:Key="SelectItem">項目を選択</system:String>
<system:String x:Key="SelectEmulatorPath">エミュレータのパスを選択</system:String>
<system:String x:Key="SelectEmulator">エミュレータを選択</system:String>
<system:String x:Key="SelectConnectionAddress">接続アドレスを選択</system:String>
<system:String x:Key="MultipleEmulatorsDetected">複数のエミュレータのインストールパスが検出されました。使用するパスを選択してください:</system:String>
<system:String x:Key="MultipleEmulatorsDetectedForConnection">複数のエミュレータが検出されました。接続するエミュレータを選択してください:</system:String>
<system:String x:Key="MultipleAddressesDetected">複数の接続アドレスが検出されました。使用するアドレスを選択してください:</system:String>
<system:String x:Key="PleaseSelectPath">パスを選択してください</system:String>
<!-- !EmulatorPathSelection -->
<system:String x:Key="PleaseSelectItem">項目を選択してください</system:String>
<system:String x:Key="EmulatorSelectionCancelled">エミュレータの選択がキャンセルされました</system:String>
<!-- !ItemSelection -->
</ResourceDictionary>

View File

@@ -1845,9 +1845,16 @@ MAA를 독립된 새 폴더에 압축 해제하거나, MAA에 속하지 않는 D
<system:String x:Key="BadModules.ResetSuccess">하드웨어 렌더링 모드로 복원되었습니다. 변경 사항을 적용하려면 MAA를 다시 시작해야 합니다. 지금 다시 시작하시겠습니까?</system:String>
<!-- !BadModules -->
<!-- EmulatorPathSelection -->
<!-- ItemSelection -->
<system:String x:Key="SelectItem">항목 선택</system:String>
<system:String x:Key="SelectEmulatorPath">에뮬레이터 경로 선택</system:String>
<system:String x:Key="SelectEmulator">에뮬레이터 선택</system:String>
<system:String x:Key="SelectConnectionAddress">연결 주소 선택</system:String>
<system:String x:Key="MultipleEmulatorsDetected">여러 에뮬레이터 설치 경로가 감지되었습니다. 사용할 경로를 선택하세요:</system:String>
<system:String x:Key="MultipleEmulatorsDetectedForConnection">여러 에뮬레이터가 감지되었습니다. 연결할 에뮬레이터를 선택하세요:</system:String>
<system:String x:Key="MultipleAddressesDetected">여러 연결 주소가 감지되었습니다. 사용할 주소를 선택하세요:</system:String>
<system:String x:Key="PleaseSelectPath">경로를 선택하세요</system:String>
<!-- !EmulatorPathSelection -->
<system:String x:Key="PleaseSelectItem">항목을 선택하세요</system:String>
<system:String x:Key="EmulatorSelectionCancelled">에뮬레이터 선택이 취소되었습니다</system:String>
<!-- !ItemSelection -->
</ResourceDictionary>

View File

@@ -1844,9 +1844,16 @@ DEBUG 目录下保存的图片有数量限制,超出后会自动清理旧图
<system:String x:Key="BadModules.ResetSuccess">已重置为硬件渲染模式。需要重启 MAA 后生效。是否立即重启?</system:String>
<!-- !BadModules -->
<!-- EmulatorPathSelection -->
<!-- ItemSelection -->
<system:String x:Key="SelectItem">选择项目</system:String>
<system:String x:Key="SelectEmulatorPath">选择模拟器路径</system:String>
<system:String x:Key="SelectEmulator">选择模拟器</system:String>
<system:String x:Key="SelectConnectionAddress">选择连接地址</system:String>
<system:String x:Key="MultipleEmulatorsDetected">检测到多个模拟器安装路径,请选择您要使用的路径:</system:String>
<system:String x:Key="MultipleEmulatorsDetectedForConnection">检测到多个模拟器,请选择您要连接的模拟器:</system:String>
<system:String x:Key="MultipleAddressesDetected">检测到多个连接地址,请选择您要使用的地址:</system:String>
<system:String x:Key="PleaseSelectPath">请选择一个路径</system:String>
<!-- !EmulatorPathSelection -->
<system:String x:Key="PleaseSelectItem">请选择一项</system:String>
<system:String x:Key="EmulatorSelectionCancelled">已取消选择模拟器</system:String>
<!-- !ItemSelection -->
</ResourceDictionary>

View File

@@ -1844,9 +1844,16 @@ DEBUG 目錄下儲存的圖片有數量限制,超出後會自動清理舊圖
<system:String x:Key="BadModules.ResetSuccess">已重置為硬體渲染模式。需要重新啟動 MAA 後生效。是否立即重新啟動?</system:String>
<!-- !BadModules -->
<!-- EmulatorPathSelection -->
<!-- ItemSelection -->
<system:String x:Key="SelectItem">選擇項目</system:String>
<system:String x:Key="SelectEmulatorPath">選擇模擬器路徑</system:String>
<system:String x:Key="SelectEmulator">選擇模擬器</system:String>
<system:String x:Key="SelectConnectionAddress">選擇連線地址</system:String>
<system:String x:Key="MultipleEmulatorsDetected">偵測到多個模擬器安裝路徑,請選擇您要使用的路徑:</system:String>
<system:String x:Key="MultipleEmulatorsDetectedForConnection">偵測到多個模擬器,請選擇您要連線的模擬器:</system:String>
<system:String x:Key="MultipleAddressesDetected">偵測到多個連線地址,請選擇您要使用的地址:</system:String>
<system:String x:Key="PleaseSelectPath">請選擇路徑</system:String>
<!-- !EmulatorPathSelection -->
<system:String x:Key="PleaseSelectItem">請選擇一項</system:String>
<system:String x:Key="EmulatorSelectionCancelled">已取消選擇模擬器</system:String>
<!-- !ItemSelection -->
</ResourceDictionary>

View File

@@ -1,54 +0,0 @@
// <copyright file="EmulatorPathSelectionDialogViewModel.cs" company="MaaAssistantArknights">
// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3.0 only as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
// </copyright>
#nullable enable
using System.Collections.Generic;
using Stylet;
namespace MaaWpfGui.ViewModels.Dialogs;
/// <summary>
/// ViewModel for EmulatorPathSelectionDialogView
/// </summary>
public class EmulatorPathSelectionDialogViewModel : PropertyChangedBase
{
/// <summary>
/// Initializes a new instance of the <see cref="EmulatorPathSelectionDialogViewModel"/> class.
/// </summary>
/// <param name="paths">可选路径列表</param>
public EmulatorPathSelectionDialogViewModel(List<string> paths)
{
Paths = paths;
if (paths.Count > 0)
{
SelectedPath = paths[0];
}
}
/// <summary>
/// Gets the list of paths.
/// </summary>
public List<string> Paths { get; }
private string? _selectedPath;
/// <summary>
/// Gets or sets the selected path.
/// </summary>
public string? SelectedPath
{
get => _selectedPath;
set => SetAndNotify(ref _selectedPath, value);
}
}

View File

@@ -0,0 +1,70 @@
// <copyright file="ItemSelectionDialogViewModel.cs" company="MaaAssistantArknights">
// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License v3.0 only as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
// </copyright>
#nullable enable
using System.Collections.Generic;
using System.Linq;
using Stylet;
namespace MaaWpfGui.ViewModels.Dialogs;
/// <summary>
/// ViewModel for ItemSelectionDialogView
/// </summary>
public class ItemSelectionDialogViewModel : PropertyChangedBase
{
/// <summary>
/// Initializes a new instance of the <see cref="ItemSelectionDialogViewModel"/> class.
/// </summary>
/// <param name="availableItems">可选项</param>
/// <param name="windowTitle">窗口标题</param>
/// <param name="promptMessage">提示信息</param>
public ItemSelectionDialogViewModel(IEnumerable<string> availableItems, string? windowTitle = null, string? promptMessage = null)
{
var itemsList = availableItems.ToList();
Items = itemsList;
WindowTitle = windowTitle ?? Helper.LocalizationHelper.GetString("SelectItem");
PromptMessage = promptMessage ?? Helper.LocalizationHelper.GetString("PleaseSelectItem");
if (itemsList.Count > 0)
{
SelectedItem = itemsList.First();
}
}
/// <summary>
/// Gets the window title.
/// </summary>
public string WindowTitle { get; }
/// <summary>
/// Gets the prompt message.
/// </summary>
public string PromptMessage { get; }
/// <summary>
/// Gets the list of items.
/// </summary>
public List<string> Items { get; }
private string? _selectedItem;
/// <summary>
/// Gets or sets the selected item.
/// </summary>
public string? SelectedItem
{
get => _selectedItem;
set => SetAndNotify(ref _selectedItem, value);
}
}

View File

@@ -357,13 +357,13 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
return;
}
// 多个路径,弹出选择框
var selectionWindow = new Views.Dialogs.EmulatorPathSelectionDialogView(detectedPaths) {
Owner = Application.Current.MainWindow,
};
if (selectionWindow.ShowDialog() == true && !string.IsNullOrEmpty(selectionWindow.SelectedPath))
var selectedPath = ShowItemSelectionDialog(
detectedPaths,
LocalizationHelper.GetString("SelectEmulatorPath"),
LocalizationHelper.GetString("MultipleEmulatorsDetected"));
if (!string.IsNullOrEmpty(selectedPath))
{
EmulatorPath = selectionWindow.SelectedPath;
EmulatorPath = selectedPath;
}
}
catch (Exception e)
@@ -373,7 +373,7 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
}
}
private static readonly string _configuredPath = ConfigurationHelper.GetValue(ConfigurationKeys.MuMu12EmulatorPath, @"C:\Program Files\Netease\MuMuPlayer-12.0");
private static readonly string _configuredPath = ConfigurationHelper.GetValue(ConfigurationKeys.MuMu12EmulatorPath, string.Empty);
private string _emulatorPath = Directory.Exists(_configuredPath) ? _configuredPath : string.Empty;
/// <summary>
@@ -557,11 +557,13 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
return;
}
// 多个路径,弹出选择框
var selectionWindow = new Views.Dialogs.EmulatorPathSelectionDialogView(detectedPaths);
if (selectionWindow.ShowDialog() == true && !string.IsNullOrEmpty(selectionWindow.SelectedPath))
var selectedPath = ShowItemSelectionDialog(
detectedPaths,
LocalizationHelper.GetString("SelectEmulatorPath"),
LocalizationHelper.GetString("MultipleEmulatorsDetected"));
if (!string.IsNullOrEmpty(selectedPath))
{
EmulatorPath = selectionWindow.SelectedPath;
EmulatorPath = selectedPath;
}
}
catch (Exception e)
@@ -571,7 +573,7 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
}
}
private static readonly string _configuredPath = ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerEmulatorPath, @"C:\leidian\LDPlayer9");
private static readonly string _configuredPath = ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerEmulatorPath, string.Empty);
private string _emulatorPath = Directory.Exists(_configuredPath) ? _configuredPath : string.Empty;
/// <summary>
@@ -845,6 +847,31 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
private const string BluestacksNxtValueName = "UserDefinedDir";
private static string? ShowItemSelectionDialog(IEnumerable<string> items, string windowTitle, string promptMessage)
{
string? ShowDialogCore()
{
var selectionWindow = new Views.Dialogs.ItemSelectionDialogView(items, windowTitle, promptMessage)
{
Owner = Application.Current.MainWindow,
};
return selectionWindow.ShowDialog() == true && !string.IsNullOrEmpty(selectionWindow.SelectedItem)
? selectionWindow.SelectedItem
: null;
}
var application = Application.Current;
if (application?.Dispatcher == null)
{
return null;
}
return application.Dispatcher.CheckAccess()
? ShowDialogCore()
: application.Dispatcher.Invoke(ShowDialogCore);
}
/// <summary>
/// Refreshes ADB config.
/// </summary>
@@ -853,7 +880,8 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
public bool DetectAdbConfig(ref string error)
{
var adapter = new WinAdapter();
List<string> emulators;
List<WinAdapter.DetectedEmulatorInfo> emulators;
WinAdapter.DetectedEmulatorInfo? selectedEmulator = null;
try
{
emulators = adapter.RefreshEmulatorsInfo();
@@ -872,12 +900,30 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
return false;
case > 1:
error = LocalizationHelper.GetString("EmulatorTooMany");
{
var selectedEmulatorDisplayText = ShowItemSelectionDialog(
[.. emulators.Select(emulator => emulator.SelectionDisplayText)],
LocalizationHelper.GetString("SelectEmulator"),
LocalizationHelper.GetString("MultipleEmulatorsDetectedForConnection"));
if (string.IsNullOrEmpty(selectedEmulatorDisplayText))
{
error = LocalizationHelper.GetString("EmulatorSelectionCancelled");
return false;
}
selectedEmulator = emulators.First(emulator => emulator.SelectionDisplayText == selectedEmulatorDisplayText);
ConnectConfig = selectedEmulator.EmulatorName;
break;
}
default:
selectedEmulator = emulators.First();
ConnectConfig = selectedEmulator.EmulatorName;
break;
}
ConnectConfig = emulators.First();
AdbPath = adapter.GetAdbPathByEmulatorName(ConnectConfig) ?? AdbPath;
AdbPath = selectedEmulator?.AdbPath ?? AdbPath;
if (string.IsNullOrEmpty(AdbPath))
{
error = LocalizationHelper.GetString("AdbException");
@@ -898,10 +944,31 @@ public class ConnectSettingsUserControlModel : PropertyChangedBase
case > 1:
{
foreach (var address in addresses.Where(address => address != "emulator-5554" && address != "1234567890ABCDEF"))
// 过滤掉默认地址
var filteredAddresses = addresses
.Where(address => address != "1234567890ABCDEF")
.ToList();
if (filteredAddresses.Count == 1)
{
ConnectAddress = address;
break;
ConnectAddress = filteredAddresses.First();
}
else if (filteredAddresses.Count > 1)
{
var selectedAddress = ShowItemSelectionDialog(
filteredAddresses,
LocalizationHelper.GetString("SelectConnectionAddress"),
LocalizationHelper.GetString("MultipleAddressesDetected"));
if (!string.IsNullOrEmpty(selectedAddress))
{
ConnectAddress = selectedAddress;
}
else
{
error = LocalizationHelper.GetString("EmulatorSelectionCancelled");
return false;
}
}
break;

View File

@@ -1,9 +1,9 @@
<hc:Window
x:Class="MaaWpfGui.Views.Dialogs.EmulatorPathSelectionDialogView"
x:Class="MaaWpfGui.Views.Dialogs.ItemSelectionDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
Title="{DynamicResource SelectEmulatorPath}"
Title="{Binding WindowTitle}"
Width="600"
Height="400"
Background="{DynamicResource RegionBrush}"
@@ -20,14 +20,14 @@
Grid.Row="0"
Margin="0,0,0,15"
FontSize="14"
Text="{DynamicResource MultipleEmulatorsDetected}"
Text="{Binding PromptMessage}"
TextWrapping="Wrap" />
<ListBox
Grid.Row="1"
Margin="0,0,0,15"
ItemsSource="{Binding Paths}"
SelectedItem="{Binding SelectedPath}">
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" TextWrapping="Wrap" />

View File

@@ -1,4 +1,4 @@
// <copyright file="EmulatorPathSelectionDialogView.xaml.cs" company="MaaAssistantArknights">
// <copyright file="ItemSelectionDialogView.xaml.cs" company="MaaAssistantArknights">
// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team)
// Copyright (C) 2021-2025 MaaAssistantArknights Contributors
//
@@ -20,28 +20,30 @@ using MaaWpfGui.ViewModels.Dialogs;
namespace MaaWpfGui.Views.Dialogs;
/// <summary>
/// EmulatorPathSelectionDialogView.xaml 的交互逻辑
/// ItemSelectionDialogView.xaml 的交互逻辑
/// </summary>
public partial class EmulatorPathSelectionDialogView
public partial class ItemSelectionDialogView
{
/// <summary>
/// Initializes a new instance of the <see cref="EmulatorPathSelectionDialogView"/> class.
/// Initializes a new instance of the <see cref="ItemSelectionDialogView"/> class.
/// </summary>
/// <param name="paths">可选路径列表</param>
public EmulatorPathSelectionDialogView(List<string> paths)
/// <param name="availableItems">可选</param>
/// <param name="windowTitle">窗口标题(可选)</param>
/// <param name="promptMessage">提示信息(可选)</param>
public ItemSelectionDialogView(IEnumerable<string> availableItems, string? windowTitle = null, string? promptMessage = null)
{
InitializeComponent();
DataContext = new EmulatorPathSelectionDialogViewModel(paths);
DataContext = new ItemSelectionDialogViewModel(availableItems, windowTitle, promptMessage);
}
/// <summary>
/// Gets the selected path.
/// Gets the selected item.
/// </summary>
public string? SelectedPath => (DataContext as EmulatorPathSelectionDialogViewModel)?.SelectedPath;
public string? SelectedItem => (DataContext as ItemSelectionDialogViewModel)?.SelectedItem;
private void OnConfirmClick(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(SelectedPath))
if (!string.IsNullOrEmpty(SelectedItem))
{
DialogResult = true;
Close();
@@ -49,7 +51,7 @@ public partial class EmulatorPathSelectionDialogView
else
{
MessageBox.Show(
Helper.LocalizationHelper.GetString("PleaseSelectPath"),
Helper.LocalizationHelper.GetString("PleaseSelectItem"),
Helper.LocalizationHelper.GetString("Tip"),
MessageBoxButton.OK,
MessageBoxImage.Warning);