IChoiceDialogService¶
IChoiceDialogService 提供了一种与平台无关的方式,用于显示带有任意按钮集的模态对话框,并返回所按按钮的结果。对话框结果可以是 string、bool、枚举值或任何其他类型。在 ViewModel 中,您可以使用 IChoiceDialogService 显示对话框并获得强类型的答案,而无需引用任何窗口类型。
主要功能包括:
- 单击对话框中的某个选择按钮(显示在对话框底部)时,对话框会自动关闭。
- 任意数量的选择按钮 — 您可以为每个按钮指定标题,并将其与按下该按钮时返回的对话框结果相关联。
- 对话框结果 — 对话框结果由所单击按钮的
Result值指定,可以是string、bool、枚举或任何其他类型。 - 可自定义的按钮位置 — 对话框按钮支持
Dock属性,可用于强制将按钮放在最前或最后。 - 默认按钮 — 您可以将特定按钮标记为默认按钮。当用户按下 ENTER 键时,对话框会调用该按钮的命令。
- 取消按钮 — 使用
IsCancel标记任意按钮,使其响应 ESC 键。 - 自动设置所有者 — 所有者窗口由底层
IDialogService通过IWindowsManager解析,因此无需显式指定。 - 选择按钮始终可用 — 与支持使用
CanOk进行验证的 IDialogService 不同,IChoiceDialogService没有根据输入状态禁用单个选项的机制。
接口定义¶
public interface IChoiceDialogService
{
// Show a modal dialog with the given choices.
T Show<T>(string message, string? caption, IReadOnlyList<DialogChoice<T>> choices);
}
| 参数 | 类型 | 说明 |
|---|---|---|
message |
string |
对话框的正文内容,赋值给对话框 ViewModel 的 Content 属性。不能为 null。 |
caption |
string? |
对话框的标题。设置为 null 时,标题取自对话框 ViewModel 的 Title 属性。 |
choices |
IReadOnlyList<DialogChoice<T>> |
以按钮形式显示在对话框底部的可用选项。顺序与按钮顺序一致。不能为 null,并且必须至少包含一项。 |
返回值:
T— 与所单击的选择按钮关联的结果- 如果通过单击对话框的关闭('x')按钮关闭对话框而未作选择,则返回
default(T)。对于引用类型(包括string),default(T)为null;对于bool类型为false;对于没有显式零成员的枚举为0。 - 按下 ENTER — 如果对话框包含
IsDefault = true的选择按钮,按下 ENTER 将返回该按钮的Result值。如果没有任何选择按钮的IsDefault = true,按下 ENTER 不会执行任何操作,对话框保持打开。 - 按下 ESC — 如果对话框包含
IsCancel = true的选择按钮,按下 Escape 将返回该按钮的Result值。如果没有任何选择按钮的IsCancel = true,按下 Escape 不会执行任何操作,对话框保持打开。
另请参阅:处理未作选择即关闭的对话框。
异常:
ArgumentNullException—message或choices参数为null。ArgumentException—choices列表为空。对话框必须至少包含一个按钮。
DialogChoice¶
对话框中的每个选择按钮都由一个 DialogChoice<T> 实例描述:
public sealed class DialogChoice<T>
{
// The button caption.
public string Caption { get; }
// The result returned by the `IChoiceDialogService.Show` method when the button is pressed.
public T Result { get; }
// Whether the current button is the default button, invoked by Enter.
public bool IsDefault { get; set; }
// Whether the current button is the cancel button, invoked by Escape.
public bool IsCancel { get; set; }
// The side to which the button is docked. Defaults to `DockType.Right`.
public DockType Dock { get; set; } = DockType.Right;
// The button order within its side. Use the `Index` property when you need to reorder buttons without changing the button array.
public int? Index { get; set; }
public DialogChoice(string caption, T result);
}
如何使用 IChoiceDialogService¶
在 ViewModel 中,调用 IChoiceDialogService.Show 方法以显示带有指定选择按钮的对话框。该方法返回所按选择按钮的 Result 值。
访问服务¶
在 ViewModel 中访问 IChoiceDialogService 对象有两种方式:
- 通过
Service<T>()辅助方法。这是获取 Eremex Controls 库附带的已注册应用程序服务的便捷方法。 - 通过构造函数注入。
Service() 辅助方法¶
在 ViewModel 中实现一个 Service<T>() 辅助方法,通过静态方法 ApplicationServicesContext.GetRequiredService<T>() 获取所请求的服务。
示例 - 使用 Service() 辅助方法显示对话框¶
using Eremex.AvaloniaUI.Controls.ApplicationServices;
using CommunityToolkit.Mvvm.Input;
public partial class MyViewModel : ObservableObject
{
// Provides access to any registered service
protected static T Service<T>() where T : class
=> ApplicationServicesContext.GetRequiredService<T>();
[RelayCommand]
private void ShowChoiceDialog()
{
// Resolve the service and show the dialog
var result = Service<IChoiceDialogService>().Show(
"The license server did not respond.",
"Activation failed",
new[]
{
new DialogChoice<string>("Show log", "log") { IsDefault = true },
new DialogChoice<string>("Retry", "retry"),
new DialogChoice<string>("Close", "close") { IsCancel = true },
});
if(result == "retry")
{
//...
}
else
{
//...
}
}
}
在 App.axaml.cs 文件中,确保按如下方式使用 SimpleServiceProvider 和 ApplicationServicesContext 注册 Eremex 应用程序服务:
public class App : Application
{
public override void OnFrameworkInitializationCompleted()
{
RegisterApplicationServices();
//...
}
static void RegisterApplicationServices()
{
// Register built-in services.
var serviceProvider = new SimpleServiceProvider();
ApplicationServicesContext.RegisterApplicationServices(serviceProvider.AddSingleton);
ApplicationServicesContext.SetCurrent(serviceProvider);
}
}
构造函数注入¶
在 ViewModel 中实现一个以 IChoiceDialogService 为参数的构造函数。实例化 ViewModel 时,将服务对象传递给该构造函数。
public partial class MyViewModel
{
private readonly IChoiceDialogService _choiceDialogService;
public MyViewModel(IChoiceDialogService choiceDialogService)
{
_choiceDialogService = choiceDialogService;
}
[RelayCommand]
private void ShowChoiceDialog()
{
var result = _choiceDialogService.Show(
"The license server did not respond.",
"Activation failed",
new[]
{
new DialogChoice<string>("Show log", "log") { IsDefault = true },
new DialogChoice<string>("Retry", "retry"),
new DialogChoice<string>("Close", "close") { IsCancel = true },
});
//...
}
}
返回字符串结果¶
要在单击对话框按钮时返回字符串值,请为该按钮使用 DialogChoice<string>。与该按钮关联的值由 DialogChoice<T> 构造函数的 result 参数指定。
以下示例显示一个带有三个按钮的对话框。特定的对话框结果(字符串值 "log"、"retry" 和 "close")与这些按钮相关联。单击其中某个按钮时,对话框的 Show 方法会返回相应的值。
[RelayCommand]
private void ShowDialogWithCustomCaptions()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<string>("Show log", "log") { IsDefault = true },
new DialogChoice<string>("Retry", "retry"),
new DialogChoice<string>("Close", "close") { IsCancel = true },
});
}
返回布尔结果¶
要在单击对话框按钮时返回布尔值,请为该按钮使用 DialogChoice<bool>。与该按钮关联的值由 DialogChoice<T> 构造函数的 result 参数指定。
以下示例显示一个带有两个按钮的对话框。特定的对话框结果(true 和 false)与这些按钮相关联。单击其中某个按钮时,对话框的 Show 方法会返回相应的值。
[RelayCommand]
private void ShowDialogWithBooleanResult()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<bool>("Show log", true) { IsDefault = true },
new DialogChoice<bool>("Close", false) { IsCancel = true },
});
}
另请参阅:处理未作选择即关闭的对话框。
返回枚举结果¶
要在单击对话框按钮时返回枚举值,请为该按钮使用 DialogChoice< enum >。与该按钮关联的值由 DialogChoice<T> 构造函数的 result 参数指定。
以下示例显示一个带有三个按钮的对话框。特定的对话框结果(DialogResult.Abort、DialogResult.Retry 和 DialogResult.Ignore)与这些按钮相关联。单击其中某个按钮时,对话框的 Show 方法会返回相应的值。
[RelayCommand]
private void ShowDialogWithEnumResult()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<DialogResult>("Abort", DialogResult.Abort) { IsCancel = true },
new DialogChoice<DialogResult>("Retry", DialogResult.Retry) { IsDefault = true },
new DialogChoice<DialogResult>("Ignore", DialogResult.Ignore),
});
}
设置按钮位置¶
使用 DialogChoice<T>.Dock 属性可以强制将特定按钮放在所有按钮的最前(将 Dock 属性设置为 DockType.Left)或最后(将 Dock 属性设置为 DockType.Right)。Dock 属性默认为 DockType.Right。
[RelayCommand]
private void ShowDialogWithCustomButtonPlacement()
{
var result = Service<IChoiceDialogService>().Show(
DialogMessage,
DialogTitle,
new[]
{
new DialogChoice<string>("Help", "help") { Dock = DockType.Left },
new DialogChoice<string>("Retry", "retry") { IsDefault = true },
new DialogChoice<string>("Cancel", "cancel") { IsCancel = true },
});
}
处理未作选择即关闭的对话框¶
当用户单击关闭('x')按钮关闭对话框时,Show 方法返回 default(T):
- 对于引用类型(
string等),结果为null。 - 对于值类型(
bool、枚举等),结果为该类型的默认值(布尔类型为false,枚举为0等)。
如果对话框包含取消按钮(IsCancel 属性为 true 的选择按钮),单击该按钮或按下 Escape 键会以该按钮的结果关闭对话框。关闭('x')按钮仍以 default(T) 结果关闭对话框。
示例 — 处理对话框的关闭¶
以下示例创建一个对话框,其中的取消按钮与 null 对话框结果相关联。在这种情况下,只需检查对话框结果是否为 null,即可处理所有关闭对话框的情形:
- 单击了取消按钮。
- 单击了标题栏的
x按钮。 - 按下了 Escape 键。
var result = Service<IChoiceDialogService>().Show(
"Save the document?",
"Confirmation",
new[]
{
new DialogChoice<bool?>("Yes", true) { IsDefault = true },
new DialogChoice<bool?>("No", false),
new DialogChoice<bool?>("Cancel", null) { IsCancel = true },
});
if (result is null)
{
// Dialog was dismissed or Cancel was clicked, or Escape was pressed.
}
else if (result.Value)
{
// Yes was pressed.
}
else
{
// No was pressed.
}
* 本页面使用机器翻译技术翻译。