フォームの上部に、編集可能なデータを下のフィールドにロードするコンボボックスがあります。ユーザーが変更を加えたが保存されておらず、コンボボックスから別のオプションを選択しようとした場合、ユーザーに警告し、キャンセルまたは保存する機会を与えたいと思います。
キャンセル可能なイベント引数を持つ「BeforeValueChange」イベントが必要です。
達成する方法について何かアドバイスはありますか?
最初に入力した場合は、ComboBoxのSelectedIndexをいつボックスに保存し、変更をキャンセルする必要がある場合はその値を復元します。
cbx_Example.Enter += cbx_Example_Enter;
cbx_Example.SelectionChangeCommitted += cbx_Example_SelectionChangeCommitted;
...
private int prevExampleIndex = 0;
private void cbx_Example_Enter(object sender, EventArgs e)
{
prevExampleIndex = cbx_Example.SelectedIndex;
}
private void cbx_Example_SelectionChangeCommitted(object sender, EventArgs e)
{
// some custom flag to determine Edit mode
if (mode == FormModes.EDIT)
{
cbx_Example.SelectedIndex = prevExampleIndex;
}
}
最も簡単な修正は次のとおりです。-
bool isSelectionHandled = true;
void CmbBx_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (isSelectionHandled)
{
MessageBoxResult result = MessageBox.Show("Do you wish to continue selection change?", this.Title, MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.No)
{
ComboBox combo = (ComboBox)sender;
isSelectionHandled = false;
if (e.RemovedItems.Count > 0)
combo.SelectedItem = e.RemovedItems[0];
return;
}
}
isSelectionHandled = true;
}
Enter
イベントに現在の値を保存します。実際のBeforeValueChange
ロジックの前に、ValueChanged
イベントにValueChanged
ロジックを実装します。ユーザーがキャンセルした場合は、保存されている値を設定し、メソッド(return
)を続行しないでください。
このシステムを頻繁に使用する場合は、ComboBoxを継承し、そこでBeforeValuechange
イベントを実装することをお勧めします。
このシナリオでは、検証イベントを使用できます
http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.validating.aspx
デフォルトでは、適切なイベントは発生しません。ユーザーがキャンセルしたい場合は、前の値をキャッシュして、その値に戻すことができます。
Validating/Validatedイベントを使用するのはどうですか?
ChangeではなくLostFocusで発生するイベントに問題がなければ、うまく機能します。
そうでなければ、どうですか
public void Combobox_ValueChanged(object sender, EventArgs e) {
if (!AskUserIfHeIsSureHeWantsToChangeTheValue())
{
// Set previous value
return;
}
// perform rest of onChange code
}
メッセージフィルター を使用して、クリックやキーの押下をインターセプトできます。これにより、コンボボックスの通常の動作を防ぐことができます。ただし、ユーザーが変更を加えたときにコンボボックスを無効にして、変更を保存するか元に戻すように要求する方がよいと思います。
実際に防ぐことはできませんが、特定の要件が満たされていない場合は、古い値に戻すことができます。
private SomeObject = selectedSomeObject=null;
private void cbxTemplates_SelectionChangeCommitted(object sender, EventArgs e)
{
if (!(sender is ComboBox cb)) return;
if (!(cb.SelectedItem is SomeObject tem)) return;
if (MessageBox.Show("You sure?", "??.",
MessageBoxButtons.OKCancel) != DialogResult.OK)
cb.SelectedItem = selectedSomeObject;
else
{
selectedSomeObject = tem;
}
}