Visual Studio 的通知和进度

通知系统

可通过多种方式通知用户 Visual Studio 中发生的情况,了解其软件开发任务。

实现任何类型的通知时:

  • 将通知数保留为最小 有效数。 通知消息应适用于大多数 Visual Studio 用户或特定功能区域的用户。 过度使用通知可能会回避用户,或者降低系统易用性。

  • 确保显示用户可用于调用相应上下文的清晰且可操作的消息 ,以便做出更复杂的选择并采取进一步操作。

  • 适当地呈现同步和异步消息。 同步通知表示需要立即注意某些内容,例如当 Web 服务崩溃或引发代码异常时。 用户应立即以需要输入的方式(例如在模式对话框中)通知这些情况。 异步通知是用户应该知道但不需要立即采取行动的通知,例如生成操作完成或网站部署完成时。 这些消息应更具环境性,而不是中断用户的任务流。

  • 仅在必要的情况下使用模式对话,防止用户在确认消息或做出对话中显示的决策之前采取进一步操作

  • 在环境通知不再有效时删除它们。 如果用户已采取措施解决他们收到通知的问题,请不要要求用户关闭通知。

  • 请注意,通知可能会导致虚假关联。 用户可能认为,一个或多个操作在事实上没有因果关系时触发了通知。 在有关上下文、触发器和通知源的通知消息中清除。

选择正确的方法

使用此表可帮助你选择正确的方法来通知用户消息。

方法 使用 请勿使用
模式错误消息对话框 在继续操作之前,需要用户响应时使用。 当无需阻止用户并中断其流时,请勿使用。 如果可能以另一种侵入性方式显示消息,请避免使用模式对话框。
IDE 状态栏 当存在有关进程状态的环境文本信息时使用。 不要单独使用。 最好与另一种反馈机制结合使用。
嵌入式信息栏 在工具窗口或文档窗口中,用于通知进度、错误状态、结果和/或可操作信息。 如果信息与放置信息栏的位置无关,请不要使用。

请勿在文档/工具窗口外使用。
鼠标光标更改 可用于通知进程正在进行。 还用于通知鼠标中存在状态更改,例如拖放正在进行时,或者鼠标光标处于特定模式,如绘图模式。 不要用于短进度更改,或者游标飘扬(例如,当绑定到较长运行进程的部分而不是整个进程时)。
进度指示器 需要报告进度(确定或不确定)时使用。 每个进度指示器类型都有各种进度指示器类型和特定用法。 请参阅 进度指示器
Visual Studio 通知窗口 “通知”窗口不公开可扩展。 但是,它用于传达有关 Visual Studio 的一系列消息,包括许可证的关键问题以及 Visual Studio 或包更新的信息通知。 不要用于其他类型的通知。
错误列表 当问题直接与用户当前打开的解决方案有问题(错误/警告/信息)相关时,他们可能需要对代码执行操作。

例如,这包括:

- 编译器消息(错误/警告/信息)

- 有关代码的代码分析器/诊断消息

- 生成消息

可能适合与项目或解决方案文件相关的问题,但首先考虑解决方案资源管理器指示。
不要用于与用户打开的解决方案代码没有任何关系的项目。
编辑器通知:灯泡 当有修补程序可用于修复打开的文件中存在的问题时使用。

请注意,灯泡还应该用于托管按需对用户代码执行的快速操作,例如重构,但在这种情况下不会显示“通知样式”。
不要用于与打开的文件没有任何关系的项目。
编辑器通知:波形曲线 用于提醒用户出现其打开代码的特定范围的问题(例如,错误的红色波浪线)。 不要用于与打开代码的特定范围无关的项目。
嵌入状态栏 用于提供与特定工具窗口、文档窗口或对话框窗口上下文中的内容或进程相关的状态。 不要用于与特定窗口中的内容没有任何关系的常规产品通知、流程或项目。
Windows 托盘通知 用于显示进程外或配套应用程序的通知。 请勿用于与 IDE 相关的通知。
通知气泡 用于通知远程进程或更改 IDE 外部 请勿用作通知用户 IDE 中的进程的方法。

通知方法

模式错误消息对话框

模式错误消息对话框用于显示需要用户确认或操作的错误消息。

Modal error message

模式错误消息对话框,提醒用户对数据库连接字符串无效

IDE 状态栏

用户注意到状态栏文本与 Windows 平台的全方位计算机体验和特定体验相关的可能性。 尽管知识渊博的 Windows 用户可能错过状态栏中的更改,但 Visual Studio 客户群往往在这两个领域都遇到。 因此,状态栏最适合用于信息性目的,或者用作其他位置提供的信息的冗余提示。 用户必须立即解决的任何类型的关键信息都应在对话框或通知工具窗口中提供。

Visual Studio 状态栏旨在允许显示多种类型的信息。 它分为反馈、设计器、进度栏、动画和客户端的区域。

反馈区域和设计器区域始终可见。 进度栏和动画区域始终是动态的,并且基于用户上下文。 设计器区域具有静态宽度,该宽度由从文本消息的随附资源中提取的字符串的长度决定。 这样,本地化就可以调整宽度的大小,而无需更改代码。 对于英语,此字符串的宽度约为 220 像素。 设计器区域的行为正常,反馈区域将吸收剩余的空间。

状态栏还经过着色,通过传达各种 IDE 状态更改(例如 IDE 处于调试模式时)来添加视觉兴趣和功能值。

IDE status bar color changes

IDE 状态栏颜色

嵌入式信息栏

可以在文档窗口或工具窗口顶部使用信息栏,以通知用户状态或条件。 它还可以提供命令,以便用户可以轻松采取措施。 Infobar 是标准 shell 控件。 避免创建自己的操作,这将在 IDE 中与其他人员不一致。 有关实现详细信息和用法指南,请参阅 信息栏

Embedded infobar

嵌入在文档窗口中的信息栏,提醒用户 IDE 处于历史调试模式,编辑器不会像在标准调试模式下那样响应。

鼠标光标更改

更改鼠标光标时,请使用绑定到 VSColor 服务的颜色,并且已与光标关联。 游标更改可用于指示正在进行的操作,以及用户将鼠标悬停在可拖动、丢弃或用于选择对象的目标上的命中区域。

仅当必须为操作保留所有可用 CPU 时间时,才使用忙碌/等待鼠标光标,从而阻止用户表达任何进一步输入。 在大多数情况下,使用多线程编写良好的应用程序时,防止用户执行其他操作的时间应很少见。

请记住,游标更改作为其他位置提供的信息的冗余提示非常有用。 不要依赖游标更改作为与用户通信的唯一方式,尤其是在尝试传达用户必须解决的关键内容时。

进度指示器

进度指示器对于在流程中向用户提供反馈非常重要,这些反馈需要几秒钟的时间才能完成。 进度指示器可以就地显示(接近正在进行的操作的启动点)、嵌入状态栏、模式对话框或 Visual Studio 状态栏中。 按照有关其使用和实现的进度指示器中的指南进行操作。

Visual Studio 通知窗口

Visual Studio 通知窗口通知开发人员有关许可、环境(Visual Studio)、扩展和更新的信息。 用户可以消除单个通知,也可以选择忽略某些类型的通知。 忽略的通知列表在“工具选项”>页中管理。

“通知”窗口当前不可扩展。

Visual Studio Notifications window

Visual Studio 通知工具窗口

错误列表

错误列表中的通知指示编译或生成过程中发生的错误和警告,并允许用户在代码中导航到该特定代码错误。

Error list

Visual Studio 中的错误列表

嵌入状态栏

由于 IDE 状态栏是动态的,因此其客户端区域上下文设置为活动文档窗口和用户上下文和/或系统响应的信息更新,因此很难持续显示信息或在长期异步进程中提供状态。 例如,IDE 状态栏不适用于多个运行和/或立即可操作项选择的测试运行结果通知。 请务必在用户进行选择或启动进程的文档或工具窗口的上下文中保留此类状态信息。

Embedded status bar

Visual Studio 中的嵌入状态栏

Windows 托盘通知

Windows 通知区域位于 Windows 任务栏上的系统时钟旁边。 许多实用程序和软件组件提供此区域中的图标,以便用户可以获取系统范围的任务的上下文菜单,例如更改屏幕分辨率或获取软件更新。

环境级通知应显示在 Visual Studio 通知中心,而不是 Windows 通知区域。

通知气泡

通知气泡可以在编辑器/设计器中显示为信息性,也可以作为 Windows 通知区域的一部分显示。 用户将这些气泡视为以后可以解决的问题,这对非关键通知来说是一个好处。 气泡不适合用户必须立即解决的关键信息。 如果在 Visual Studio 中使用通知气泡,请按照 Windows 桌面指南操作通知气泡

Notification bubble

用于 Visual Studio 的 Windows 通知区域中的通知气泡

进度指示器

进度指示器是通知系统提供用户反馈的重要部分。 他们将告诉用户进程和操作何时完成。 熟悉的指示器类型包括进度条、旋转光标和动画图标。 进度指示器的类型和位置取决于上下文,包括所报告的内容以及完成过程或操作需要多长时间。

因素

若要确定哪个指示器类型合适,需要确定以下因素。

  1. 计时: 操作需要的时间长度

  2. 模态: 操作是否为环境模式(在进程完成之前锁定 UI)

  3. 持久性/暂时性: 是否需要在以后报告进度的最终结果和/或可查看

  4. 确定/不确定: 是否可以计算操作结束时间和进度

  5. 图形/文本位置: 进度或进程是内联捕获的、消息正文中还是特定控件,如树控件

  6. 邻近度: 进度是否应与它相关的 UI 接近。 (例如,它可以位于状态栏中,可能很远,或者它是否必须靠近启动进程的按钮?

确定进度

进度类型 何时和如何使用 说明
进度栏 (确定) 预期持续时间为 >5 秒。

可能包括进程详细信息的文本说明。
不要 将文本嵌入动画中。
信息栏 与上下文 UI 关联的消息传送。 请参阅 信息栏

可能包括进程详细信息的文本说明。
当需要指示多个进程时,请勿 使用多个信息栏。 请改用堆积进度条。
输出窗口 暂时性通知:用户希望 查看 完成后的详细信息的应用级进程。 如果用户稍后需要引用数据,请不要使用。
日志文件 在完成后保存详细信息非常重要时,与不妥协的通知配对。
状态栏 暂时性通知:用户 完成后不需要 详细信息的应用级进程。

包括嵌入的进度栏。

可能包括进程详细信息的文本说明。

不确定进度

进度类型 何时和如何使用 说明
进度栏 (不确定) 预期持续时间为 >5 秒。

可能包括进程详细信息的文本说明。
不要 将文本嵌入动画中。
蚂蚁 (动画水平点) 往返服务器。

放置在父容器顶部的近上下文点。
如果不是由整个容器父级,请勿 使用。
旋转器 (进度环) 与上下文 UI 关联的进程,或空间是一个考虑因素。

可能包括进程详细信息的文本说明。
信息栏 与上下文 UI 关联的消息传送。 请参阅 信息栏 当需要指示多个进程时,请勿 使用多个信息栏。 请改用堆积进度条。
输出窗口 暂时性通知:用户希望 查看 完成后的详细信息的应用级过程。 不要 用于需要跨会话保留的信息。
日志文件 在完成后保存详细信息非常重要时,与不妥协的通知配对。
状态栏 暂时性通知:用户 完成后不需要 详细信息的应用级进程。

包括嵌入进度栏。

可能包括进程详细信息的文本说明。

进度指示器类型

进度栏

不确定

Indeterminate progress bar

不确定进度栏

“不确定”表示无法确定操作或进程的总体进度。 对需要无限时间或访问未知数量的对象的操作使用不确定进度条。 使用文本说明来配合所发生的事情。 使用超时为基于时间的操作提供边界。 不确定进度条使用动画来显示正在进行进度,但不提供其他信息。 不要仅根据可能缺乏准确性而选择不确定进度条。

确定

Determinate progress bar

确定进度栏

“确定”表示操作或进程需要有限时间,即使无法准确预测该时间量。 明确指示完成。 除非操作已完成,否则不要让进度栏达到 100%。 确定进度栏动画从 0 向右移动 0 到 100%。

切勿在操作期间向后移动进度指示器。 当操作开始时,条形图应稳步向前移动,并在操作结束时达到 100%。 进度栏的要点是让用户了解整个操作需要多长时间,而不考虑涉及多少步骤。

并发报告(堆积进度条)

如果某个操作需要很长时间(也许几分钟),则可以使用两个进度条,一个显示操作的总体进度,另一个用于当前步骤的进度。 例如,如果安装程序正在复制多个文件,则可以使用一个进度栏来指示整个进程需要多长时间,而一秒钟可以指示正在复制当前文件或目录的百分比。 不要使用堆积进度条报告五个以上的并发操作或进程。 如果有五个以上的并发操作或要报告的进程,请使用带有“取消”按钮的模式对话框,并将进度详细信息报告到“输出”窗口。

文本说明

使用文本说明来配合所发生的事情和估计完成时间。 如果无法确定操作需要多长时间,则提供反馈的更好选择可能是动画图标而不是进度栏。

Visual Studio 在状态栏中提供标准进度栏,可供集成到 Visual Studio 中的任何产品使用。 对于进度栏动画时所发生情况的文本说明,可以更新状态栏文本。

其他进度指示器

蚂蚁 (动画水平点)

Progress ants

“Ants”,动画水平点,为不确定往返服务器进程提供视觉参考。

旋转器 (进度环)

Progress spinner

微调器(也称为“进度环”)是一个不确定的进度指示器,主要用于上下文 UI。 在与其相关内容(如文本类别标头、消息或控件)附近显示旋转器。

游标反馈

对于需要 2-7 秒的操作,请提供游标反馈。 通常,这意味着使用操作系统提供的等待游标。 有关指南,请参阅 MSDN 文章 Cursors.Wait 属性

进度指示器位置

状态栏

状态栏为应用程序提供一个位置,用于向用户显示消息和有用信息,而不会中断用户的工作。 通常显示在窗口底部,进度状态将是一个工具提示窗格,其中包含有关进度度量与进度栏指示器相结合的消息。

Status bar with progress bar

具有进度栏的状态栏

Status bar with messaging

带有文本说明的状态栏

信息栏

与状态栏类似,信息栏提供上下文通知和消息传送,也可以与不确定进度指示器(如进度栏或微调器)配对。 信息栏不应提供精细级别进度或确定进度指示。 请参阅 信息栏

Infobar with progress bar and messaging

包含进度栏和文本说明的信息栏

Infobar inside a window

内联

内联进度指示可由任何进度加载程序类型表示。 通常进度指示器与消息传送配对,但这不是一项要求。

Inline progress spinner

旋转器与文本说明相结合

Inline stacked progress bars

确定堆积进度条

Inline progress messaging

服务器资源管理器内联文本:正在刷新...

工具窗口

全局进度指示由位于工具栏正下方的不确定进度栏表示。

Global indeterminate progress bar

团队资源管理器全局不确定进度栏

对话框

对话框可以包含任何进度加载程序类型。 进度指示器可以与消息传送配对,并结合多个级别的进度指示来表示粒度和子进程。

Dialog with multiple progress indicator types

包含并发进程和多个进度指示器类型的 Visual Studio 对话框

Dialog with progress loader and messaging

Visual Studio 对话框,其中包含进度加载器和消息传送内联命令

文档井

文档可以结合使用控件显示多个进度加载程序类型。

Progress messaging in document well

工具栏下方不确定进度栏

输出窗口

“输出”窗口适用于通过内联文本消息处理进程进度和正在进行的进度状态。 应使用状态栏以及任何输出窗口进度报告。

Progress messaging in Output Window

进程状态和等待消息传送的输出窗口

信息栏

信息栏为用户提供接近其关注点的指示器,并使用共享信息栏控件可确保视觉外观和交互的一致性。

Infobar

Visual Studio 中的信息栏

信息栏的相应用途

  • 向用户提供与当前上下文相关的非阻止但重要消息

  • 指示 UI 处于具有某些交互影响的特定状态或条件,例如历史调试

  • 通知用户系统检测到问题,例如当扩展导致性能问题时

  • 为用户提供一种轻松执行操作的方法,例如当编辑器检测到文件具有混合选项卡和空格时

应做事项:
  • 使信息栏消息文本简短且指向该点。

  • 在链接和按钮上保留文本简洁。

  • 确保向用户提供的“操作”选项最少,仅显示所需的操作。

禁止事项:
  • 使用信息栏提供应放置在工具栏中的标准命令。

  • 使用信息栏代替模式对话框。

  • 在窗口外创建浮动消息。

  • 在同一窗口中的多个位置使用多个信息栏。

多个信息栏是否可以同时显示?

是的,多个信息栏可以同时显示。 它们将显示为先到先得的第一服务订单,第一个信息栏显示在顶部,其他信息栏如下所示。

用户一次最多会看到三个信息栏,之后,如果有更多信息栏可用,信息栏区域将变为可滚动。

创建信息栏

信息栏有四个部分,从左到右:

  • 图标: 可在其中添加要为信息栏显示的任何图标,例如警告图标。

  • 文本: 可根据需要添加文本来描述方案/情况用户以及文本中的链接。 请记得保持文本简洁。

  • 操作: 本部分应包含用户可以在信息栏中执行的操作的链接和按钮。

  • 关闭按钮: 右侧的最后一部分可以有关闭按钮。

在托管代码中创建标准信息栏

InfoBarModel 类可用于为信息栏创建数据源。 使用以下四个构造函数之一:

public InfoBarModel(IEnumerable<IVsInfoBarTextSpan> textSpans, ImageMoniker image = default(ImageMoniker), bool isCloseButtonVisible = true);

public InfoBarModel(string text, ImageMoniker image = default(ImageMoniker), bool isCloseButtonVisible = true);

public InfoBarModel(IEnumerable<IVsInfoBarTextSpan> textSpans, IEnumerable<IVsInfoBarActionItem> actionItems, ImageMoniker image = default(ImageMoniker), bool isCloseButtonVisible = true);

public InfoBarModel(string text, IEnumerable<IVsInfoBarActionItem> actionItems, ImageMoniker image = default(ImageMoniker), bool isCloseButtonVisible = true);

以下示例使用超链接、操作按钮和图标创建包含一些文本的 InfoBarModel。

Infobar with hyperlink

var infoBar = new InfoBarModel(
    textSpans: new[]
    {
        new InfoBarTextSpan("This is a "),
        new InfoBarHyperlink("hyperlink"),
        new InfoBarTextSpan(" InfoBar.")
    },
    actionItems: new[]
    {
        new InfoBarButton("Click Me")
    },
    image: KnownMonikers.StatusInformation,
    isCloseButtonVisible: true);

在本机代码中创建标准信息栏

实现 IVsInfoBar 接口,以便从本机代码提供信息栏。

public interface IVsInfoBar
{
    IVsInfoBarActionItemCollection ActionItems { get; }
    ImageMoniker Image { get; }
    bool IsCloseButtonVisible { get; }
    IVsInfoBarTextSpanCollection TextSpans { get; }
}

从信息栏获取信息栏 UIElement

InfoBarModel 或 IVsInfoBar 实现是必须转换为 UIElement 才能在 UI 中显示的数据模型。 可以使用 SVsInfoBarUIFactory/IVsInfoBarUIFactory 服务检索 UIElement。

private bool TryCreateInfoBarUI(IVsInfoBar infoBar, out IVsInfoBarUIElement uiElement)
{
    IVsInfoBarUIFactory infoBarUIFactory = serviceProvider.GetService(typeof(SVsInfoBarUIFactory)) as IVsInfoBarUIFactory;
    if (infoBarUIFactory == null)
    {
        uiElement = null;
        return false;
    }

    uiElement = infoBarUIFactory.CreateInfoBar(infoBar);
    return uiElement != null;
}

放置

可以在以下一个或多个位置显示信息栏:

  • 工具窗口

  • 在文档选项卡中

重要

可以将信息栏定位为提供有关全局上下文的消息。 这将显示在工具栏和文档之间。 不建议这样做,因为它会导致 IDE 的“跳转和混蛋”问题,除非绝对必要且适用,否则应避免此问题。

在 ToolWindowPane 中放置信息栏

ToolWindowPane.AddInfoBar(IVsInfoBar) 方法可用于向工具窗口添加信息栏。 此 API 可以添加 IVsInfoBar(其中 InfoBarModel 是默认实现),也可以添加 IVsUIElement。

在文档或非 ToolWindowPane 中放置信息栏

若要将信息栏放入任何 IVsWindowFrame,请使用 VSFPROPID_InfoBarHost 属性获取帧的 IVsInfoBarHost,然后添加信息栏 UIElement。

private void AddInfoBar(IVsWindowFrame frame, IVsUIElement uiElement)
{
    IVsInfoBarHost infoBarHost;
    if (TryGetInfoBarHost(frame, out infoBarHost))
    {
        infoBarHost.AddInfoBar(uiElement);
    }
}
private bool TryGetInfoBarHost(IVsWindowFrame frame, out IVsInfoBarHost infoBarHost)
{
    object infoBarHostObj;
    if (ErrorHandler.Failed(frame.GetProperty((int)__VSFPROPID7.VSFPROPID_InfoBarHost, out infoBarHostObj)))
    {
        infoBarHost = null;
        return false;
    }

    infoBarHost = infoBarHostObj as IVsInfoBarHost;
    return infoBarHost != null;
}

在主窗口中放置信息栏

若要在主窗口中放置信息栏,请使用 IVsShell 服务的VSSPROPID_MainWindowInfoBarHost获取主窗口的 IVsInfoBarHost,然后将信息栏 UIElement 添加到其中。

我是否会知道用户何时在信息栏中执行操作?

是的,我们会将每个事件操作返回到信息栏作者。 然后,信息栏作者根据信息栏中的用户选择在 IDE 中执行操作。 如果关闭后需要删除其他信息栏,将自动从单击“关闭”按钮的主机中删除信息栏,但需要执行其他工作。 遥测还需要由每个信息栏独立记录。

在 ToolWindowPane 中接收信息栏事件

ToolWindowPane 有两个信息栏事件。 当 ToolWindowPane 中的信息栏关闭时,将引发 InfoBarClosed 事件。 单击信息栏内的超链接或按钮时,将引发 InfoBarActionItemClicked 事件。

直接从 UIElement 接收信息栏事件

IVsInfoBarUIElement.Advise 可用于直接从信息栏的 UIElement 订阅事件。 实现 IVsInfoBarUIEvents 将允许作者接收关闭和单击事件。

public interface IVsInfoBarUIEvents
{
    void OnActionItemClicked(IVsInfoBarUIElement infoBarUIElement, IVsInfoBarActionItem actionItem);
    void OnClosed(IVsInfoBarUIElement infoBarUIElement);
}

错误验证

当用户输入不可接受的信息(例如,当跳过所需字段或以不正确的格式输入数据时),最好在控件附近使用控件验证或反馈,而不是使用阻止弹出错误对话框。

字段验证

窗体和字段验证由三个组件组成:控件、图标和工具提示。 虽然多种类型的控件可以使用此功能,但文本框将用作示例。

Field validation (blank)

如果字段是必需的,则应有水印文本,指出“必需>”,字段背景应为浅黄色(VSColor: Environment.ControlEditRequiredBackground),前景应为灰色(VSColor: Environment.ControlEditRequiredHintText):<

Field validation with

程序可以确定当焦点移动到另一个控件或用户单击 [确定] 提交按钮或用户保存文档或窗体时,控件处于无效内容的状态

确定无效的内容状态后,图标会显示在控件内或就在控件旁边。 描述错误的工具提示应显示在图标或控件的悬停上。 此外,在创建无效状态的控件周围应显示一个 1 像素边框。

Field validation layout specifications

字段验证的布局规范

图标位置的可接受变体

存在无数的唯一情况,用户需要了解验证错误。 考虑 UI 的控件类型和配置,选择适合你的情况的图标位置。

Acceptable locations for icon location

字段验证图标位置的可接受变体

需要往返服务器或网络连接的验证

在某些情况下,需要往返服务器来验证内容,并且必须显示用户进度、已验证和错误状态。 下图显示了此示例和建议的 UI。

Validation involving a round trip to a server

涉及往返服务器的验证

请注意,必须提供控件右侧足够的可用空间,以便容纳“正在验证...”和“重试”文本。

就地警告文本

当有可用空间将错误消息置于接近控件的错误状态时,最好单独使用工具提示。

In-place warning

就地警告文本

水印

有时整个控件或窗口处于错误状态。 在这种情况下,请使用水印来指示错误。

Watermark

水印字段验证