I have created a custom CollectionEditor
but I want to validate my collection when the user clicks the 'OK' button. I've tried the following:
protected override CollectionForm CreateCollectionForm()
{
_form = base.CreateCollectionForm();
_form.FormClosing += _form_FormClosing;
return _form;
}
So that when the user clicks OK it fires the _form_Closing event. This works however when I do this:
private void _form_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = !Validate();
}
And Validate
returns false
(telling the form not to close) all of the existing members of the collection are removed from the UI
. Surely the items of the collection shouldn't disappear from the UI
?
Is there something else I need to call?
OK so it's not elegant but it does work.
Get the ListBox like so
_listBox = _form.Controls[0].Controls[4] as ListBox;
Store it as a member variable and then handle the MouseDown event on the OK button like so
Button btnOK = _form.AcceptButton as Button;
btnOK.MouseDown += btnOK_MouseDown;
Then create a list or array of objects in the class and copy them into the array on MouseDown (you can't do MouseClick as by then they are gone).
void btnOK_MouseDown(object sender, MouseEventArgs e)
{
_objects = new List<object>();
foreach (object listItem in _listBox.Items)
{
_objects.Add(listItem);
}
}
Then on Form_Closing if the collection doesn't pass validation then add them back in.
if(!CheckValidEntities(_value as IEnumerable<Entity>))
{
e.Cancel = true;
foreach (object listItem in _objects)
{
_listBox.Items.Add(listItem);
}
}
I don't love it and it is a little hacky but it seems to work.
Still a hack but this preserves the state of the dialog. This works no matter if the button was clicked with the mouse or the keyboard.
protected override CollectionForm CreateCollectionForm()
{
this.Form = base.CreateCollectionForm();
var okButton = this.Form.AcceptButton as Button;
// replace the OK button current eventHandler.
var okClickDelegate = this.RemoveClickEvent(okButton);
okButton.Click += (sender, e) =>
{
// Validate your items
var isValid = this.ValidateItems();
if (isValid)
{
okClickDelegate.DynamicInvoke(sender, e);
}
this.preventClose = !isValid;
};
}
private void Form_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
e.Cancel = this.preventClose;
this.preventClose = false;
}
/// <summary>
/// Removes the click event handler of a button.
/// </summary>
/// <param name="b">The button to remove the click event.</param>
/// <returns>A Delegate representing the remove event.</returns>
private Delegate RemoveClickEvent(Button b)
{
FieldInfo f1 = typeof(Control).GetField("EventClick", BindingFlags.Static | BindingFlags.NonPublic);
object obj = f1.GetValue(b);
PropertyInfo pi = b.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
var handler = list[obj];
list.RemoveHandler(obj, handler);
return handler;
}
The function to remove the events was taken from: https://stackoverflow.com/a/91853/1698342
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.