我正在开发一个
Windows应用程序,它包含一个包含大量项目的ListView.
当用户点击某个项目时,该应用会显示该项目的详细信息.该
用户然后有机会编辑这些细节.用户应该单击
每次更改后都会保存按钮,但当然并不总是会发生.
当用户点击某个项目时,该应用会显示该项目的详细信息.该
用户然后有机会编辑这些细节.用户应该单击
每次更改后都会保存按钮,但当然并不总是会发生.
如果用户进行更改但未单击“保存”,则应用程序将显示一条消息
框询问他们是否愿意保存他们的更改.此框包含取消
按钮,如果他们点击取消,我想短路选择
另一个项目并将用户保持在他们正在编辑的那个项目上.
我找不到这样做的方法,如果项目更改而不保存,我会显示itemselecedchanged事件中的对话框,如果用户单击取消,我从事件中删除我的功能并手动更改所选项目,之后我返回事件的功能,但在此之后,事件调用和我手动选择的项目未被选中.
private bool EnsureSelected() { bool continue_ = true; if (_objectChange) { var res = MessageBox.Show("Do you want to save changes?","Warning",MessageBoxButtons.YesNoCancel,MessageBoxIcon.Warning); switch (res) { case DialogResult.Cancel: if (!string.IsNullOrEmpty(_selectedKey)) { listView_Keys.ItemSelectionChanged -= listView_Keys_ItemSelectionChanged; listView_Keys.Focus(); listView_Keys.Items[_selectedKey].Selected = true; listView_Keys.ItemSelectionChanged += listView_Keys_ItemSelectionChanged; } continue_ = false; break; case DialogResult.Yes: button_Save.PerformClick(); _objectChange = false; break; case DialogResult.No: _objectChange = false; break; default: throw new ArgumentOutOfRangeException(); } } return continue_; }
更新::
我试过这个解决方案:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private ListViewItem currentSelection = null; private bool pending_changes = false; private void listView1_ItemSelectionChanged(object sender,ListViewItemSelectionChangedEventArgs e) { if (e.Item == currentSelection) { // if the current Item gets unselected but there are pending changes if (!e.IsSelected && pending_changes) { var res = MessageBox.Show("Do you want to save changes?",MessageBoxIcon.Warning); switch (res) { case DialogResult.Cancel: // we dont want to change the selected item,so keep it selected e.Item.Selected = true; break; case DialogResult.Yes: //button_Save.PerformClick(); pending_changes = false; break; case DialogResult.No: pending_changes = false; break; default: throw new ArgumentOutOfRangeException(); } } } else // not the selected button { if (!pending_changes && e.IsSelected) { // Item may be selected and we save it as the new current selection currentSelection = e.Item; } else if (pending_changes && e.IsSelected) { // Item may not be enabled,because there are pending changes e.Item.Selected = false; } } } private void Form1_Load(object sender,EventArgs e) { listView1.Items[0].Selected = true; } private void button1_Click(object sender,EventArgs e) { pending_changes = true; } }
但是这没有用,第一次挂起的更改是真的,消息框调用了两次,第二次没有发生任何事情.
解决方法
首先,每当您选择另一个项目时,该事件应该触发两次.
首先取消选择的项目(其中e.IsSelected为false)
第二个是选中的项目(其中e.IsSelected为true)
假设您有一个设置的标志pending_changes,每当有未保存的更改时,下面的代码应该取消项目选择.
不幸的是,无论何时显示MessageBox,listView都会再次失去焦点.当您单击MessageBox时,焦点将返回到listView,这会导致控件再次触发其事件.这就是为什么需要一个肮脏的解决方法,需要记住我们在消息框上单击“取消”并再次对下一个事件执行操作.
private ListViewItem currentSelection = null; private bool pending_changes = false; private bool cancel_flag = false; private void listView1_ItemSelectionChanged(object sender,ListViewItemSelectionChangedEventArgs e) { Console.WriteLine("Item " + e.ItemIndex + " is now " + e.IsSelected); if (e.Item != currentSelection) { // if another item gets selected but there are pending changes if (e.IsSelected && pending_changes) { if (cancel_flag) { // this handles the second mysterIoUs event cancel_flag = false; currentSelection.Selected = true; e.Item.Selected = false; return; } Console.WriteLine("uh oh. pending changes."); var res = MessageBox.Show("Do you want to save changes?",MessageBoxIcon.Warning); switch (res) { case DialogResult.Cancel: // we dont want to change the selected item,so keep it selected currentSelection.Selected = true; e.Item.Selected = false; // for some reason,we will get the same event with the same argments again,// after we click the cancel button,so remember our decision cancel_flag = true; break; case DialogResult.Yes: // saving here. if possible without clicking the button,but by calling the method that is called to save pending_changes = false; currentSelection = e.Item; break; case DialogResult.No: pending_changes = false; currentSelection = e.Item; break; default: throw new ArgumentOutOfRangeException(); } } else if (e.IsSelected && !pending_changes) { currentSelection = e.Item; } } }