How can be combo box value change process interrupted?
我正在用可视化界面编写 c#。部分逻辑由一组值组成,这些值的变化取决于在组合框中选择了其中一个(集合)。
值集的更改可以保存或不保存。当用户在组合框中选择不同的项目(集合)时,需要为用户提供保存未保存的更改或拒绝它们的机会。当带有是/否的消息框出现时,组合框仍然显示旧值是必要的,只有在那之后,根据用户的选择显示新的或旧的。
顺序应该是:
用户使用键或下拉菜单选择新项目 -> 事件被触发并且表单停止所有处理 -> 我的代码取消更改或让它通过 ->(如果未取消)组合框被重绘新值。
注意尝试了以下事件并证明是不够的:
- SelectedIndexChanged
- 选定值已更改
- 选择更改提交
- 证实
- 下拉关闭
我找到了一些可以接受的解决方案,尽管不直接对应于所问问题的详细说明。
但遗憾的是,由于某种原因被他的建议者删除,一个可能的解决方案是使用消息过滤器。然而,这导致了手动计算鼠标点击位置的路径,并且基本上用我自己的一些粗略的拐杖将翻译鼠标事件的winforms功能替换为更改组合框下拉列表中的选定项目的过程。这是我回避的路径。
最后我选择了"化妆品"解决方案,其想法是在用户决定是否取消更改的过程中替换组合框中显示的文本。
所以,在 SelectedIndexChanged 事件中,我已经放置了以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | try { if (MyDataSets.Current.HasChanges() && !MyDataSets.Current.Name.Equals(cbChosenDataSet.Value)) { cbChosenDataSet.DropDownStyle = ComboBoxStyle.DropDown; cbChosenDataSet.Text = MyDataSets.Current.Name + ' '; Application.DoEvents(); } else return; /* * UserChoseToCancel is set according to user's choice */ if (UserChoseToCancel) cbChosenDataSet.Value = MyDataSets.Current.Name; else MyDataSets.SetCurrent(cbChosenDataSet.Value); /* * other things */ } catch(Exception e) {/* handling */} finally { cbChosenDataSet.DropDownStyle = ComboBoxStyle.DropDownList; } |
这个想法的要点是:在 DropDown 样式的 ComboBox\\' 中,可以根据需要更改文本。但是,当设置为列表中的一项时,将发生选择更改。为了避免这种不必要的情况,临时文本中添加了一个空格。
如果取消没有发生,将样式恢复为 DropDownList 会强制将文本更改为实际选择的值(保持不变)。
如果用户取消更改,组合框的值将恢复为旧值。处理程序开头的检查会阻止由该处理程序生成的事件被进一步处理。
我认为这就是您所追求的 - 每当更改值时,都会提示用户确定/取消。唯一的限制是组合框在显示消息框时显示新值,直到用户单击取消。也许通过拦截绘制消息可以防止这种情况发生。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class MyCombo : ComboBox { // Keep track of the previous value int previousIndex = 0; // Determines whether the OnSelectedIndexChanged is ignored bool ignoreChangedEvent = false; /// <summary> /// Raises the <see cref="E:System.Windows.Forms.ComboBox.SelectedIndexChanged"/> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param> protected override void OnSelectedIndexChanged(EventArgs e) { if (!ignoreChangedEvent) { // Prompt the user to see if they really want to change. if (MessageBox.Show("Change value?", Application.ProductName, MessageBoxButtons.OKCancel) == DialogResult.Cancel) { ignoreChangedEvent = true; base.SelectedIndex = previousIndex; } else { previousIndex = base.SelectedIndex; } } else { ignoreChangedEvent = false; } base.OnSelectedIndexChanged(e); } } |