我有 2 个ComboBox
控件。如果用户从ComboBox1
中选择A,我希望ComboBox2
中的A灰显且不可选择。可以这样做吗?又如何??
BOOL CEngravingCalculatorDlg::OnInitDialog()
{
CComboBox* empcombo1 = static_cast<CComboBox*>(GetDlgItem(IDC_COMBO1));
empcombo1->AddString(L"A");
empcombo1->AddString(L"B");
empcombo1->AddString(L"C");
empcombo1->SetCurSel(0);
UpdateData(FALSE);
CComboBox* empcombo2 = static_cast<CComboBox*>(GetDlgItem(IDC_COMBO2));
empcombo2->AddString(L"A");
empcombo2->AddString(L"B");
empcombo2->AddString(L"C");
empcombo2->SetCurSel(0);
UpdateData(FALSE);
}
标准ComboBox
没有禁用/不可选择项目的概念。
您可以:
-
只需根据需要动态地在
ComboBox
中添加/删除项目。例如,如果用户在ComboBox1
中选择"A",然后从ComboBox2
中删除"A",如果用户选择ComboBox1
中的任何其他内容,则将"A"重新添加到ComboBox2
。 -
自定义绘制
ComboBox
以使不可选择的项目显示为禁用。如果用户尝试选择"禁用"项目,请忽略它,和/或只选择附近未"禁用"的项目。
抵制乐于助人的诱惑。它会导致灾难性的用户体验。相反,请在设计 UI 时遵循以下原则:
- 允许用户随时输入任何数据
- 通过 en-/禁用"确定"/"提交"按钮以响应输入来防止 UI 向应用程序提交无效数据
- [奖励:除了禁用的"确定"/"提交"按钮外,在交互点附近提供视觉提示,以便对无效/不一致的数据进行即时视觉反馈]
标准组合框控件不支持问题所要求的内容,MFC 也没有提供任何实用工具实现来实现这一点(更容易)。即使有可能,它也可能会产生一个糟糕的界面,用户会认为这是敌对的。
阅读这里的字里行间,我猜问题是询问输入验证,规则是不能同时从两个组合框中选择相同的条目。虽然这是一个有效的约束,但允许用户暂时违反该约束是导致用户体验不佳的原因(Raymond Chen 在他的博客文章中评论了这种方法的问题WM_KILLFOCUS
这是进行字段验证的错误时间)。
为了说明这在实践中是如何实现的,请考虑一个用户尝试输入A
B
,但在中途决定选择B
A
。这是他们的故事:
- 用户从CB1中选择
A
(计划输入A
B
) - 用户改变了主意,现在决定在与CB2交互时改用
B
A
- 用户意识到他们无法从CB2中选择
A
,因此他们选择了下一个最接近的B
- 用户回到CB1并意识到他们无法选择
B
(他们的最终目标),因此他们选择了唯一可用的条目:C
- 用户现在回到CB2输入
A
(他们一直计划这样做) - 用户导航回CB1以输入
B
本应采取 3 个步骤的事情变成了令人困惑的寻宝游戏,UI 在每一步都进行了反击。
这不是任何人想要与之交互的 UI,因此最好放弃这个想法。更好的方法是进行非侵入式输入验证:每当用户从任一组合框中选择一个条目时,验证输入是否有效,并禁用"确定"/"提交"/任何按钮。
这可以防止应用程序接收无效输入,但仍允许用户临时输入无效数据。还可以考虑在仍包含无效数据的控件旁边放置视觉提示,例如警告图标 (⚠️),以便用户立即收到反馈。
由于此问题带有 mfc 标记:MFC 提供了自己的对话数据验证 (DDV) 系统。虽然这使用起来很方便,但它无法提供即时的视觉反馈,并且没有预定义的例程来验证需要在多个控件之间保持一致的输入。