.NET Forum / Languages / C# / December 2005
Validation and Undo
|
|
Thread rating:  |
John Richardson - 14 Dec 2005 21:27 GMT General question about how WinForms handles undoing a change during a control's validation, if it does at all. After a change to a control's value, if the data is determined to be invalid, then in the control's Validating event handler, setting e.Cancel = true will prevent the offending control from losing focus until the data in the control is good.
If the user wants to revert to the original data, say by hitting ESC, does the form have any kinds of default behaviours for this kind of action (ie: undoing a change)? Or do I have to program this whole undo process manually?
This could entail overriding the ProcessCmdKey and looking for ESC, and storing the value of the control before the control receives focus so I can reset it after ESC is hit.
I had thought that this was a default behaviour for some reason, but testing this out reveals this not to be the case for my TextBox.
Are there any suggestions for a better way to implement a simple undo?
Nicholas Paldino [.NET/C# MVP] - 14 Dec 2005 21:38 GMT John,
The TextBox has undo capability, but you don't know how many changes have been made, so you just can't unwind the undo stack.
Rather, you will have you go to the data source and get the original value (or, store the original value when binding occurs). That's the only way you can be sure of the original value.
Hope this helps.
 Signature - Nicholas Paldino [.NET/C# MVP] - mvp@spam.guard.caspershouse.com
> General question about how WinForms handles undoing a change during a > control's validation, if it does at all. [quoted text clipped - 16 lines] > > Are there any suggestions for a better way to implement a simple undo? John Richardson - 15 Dec 2005 01:17 GMT >The TextBox has undo capability Is this only for a databound context? I looked at the interface for the textbox and I couldn't see where the previous value of the control would be stored... and I don't need a whole undo history. That being said, I'll probably build it myself anyways to give myself some flexibility.
> John, > [quoted text clipped - 27 lines] >> >> Are there any suggestions for a better way to implement a simple undo? Joanna Carter [TeamB] - 15 Dec 2005 10:45 GMT | >The TextBox has undo capability | | Is this only for a databound context? I looked at the interface for the | textbox and I couldn't see where the previous value of the control would be | stored... and I don't need a whole undo history. That being said, I'll | probably build it myself anyways to give myself some flexibility. I can't see the previous messages in this thread, has the subject changed ?
In the absence of other replies, can I suggest you look at implementing IEditableObject in the class whose instances you are editing. If you are linking to a database table, then I thought that the record datatype had undo facilities. It is not the job of the edits to maintain undo information, that is the job of the class supplying the data.
Joanna
 Signature Joanna Carter [TeamB] Consultant Software Engineer
John Richardson - 15 Dec 2005 18:58 GMT >It is not the job of the edits to maintain undo information, that is the >job of the class supplying the data. I think that I might disagree with this. I think that there should be 2 levels of editing/undoing: the individual field, and the "row", or more generally, a set of fields. A typical form interaction will be to load data, edit various fields, and then indicate that the data should be saved -> this is the transaction that should be class level.
But, as the user edits a field, the control itself offers a Validation event, which is hinting at a Transaction at the control level. So, a Field transaction should be viewed as beginning when the control is focused, ending when the control is unfocused, and I would think that a cancel should be implemented by ESC, or some other commonly understood method.
For some reason, I figured this was a default behaviour of the Control object, but it is not. In my view, this behaviour is fairly natural assumption... it makes more sense than say the SHIFT-SPACE behaviour on the datagrid, that is for sure.
> | >The TextBox has undo capability > | [quoted text clipped - 14 lines] > > Joanna Joanna Carter [TeamB] - 15 Dec 2005 20:45 GMT | But, as the user edits a field, the control itself offers a Validation | event, which is hinting at a Transaction at the control level. So, a Field [quoted text clipped - 6 lines] | assumption... it makes more sense than say the SHIFT-SPACE behaviour on the | datagrid, that is for sure. FMPOV, the Validating event in the Control class fits very well into the Model View Presenter framework as it is a response to a user interaction trying to quit editing a value.
The edit is a means of entering data that will be passed to the underlhying data member. The Validating event gives the program an opportunity to interrupt the flow of data to the data member and prompt the edit to refresh itself to the, as yet unchanged, underlying data member.
Joanna
 Signature Joanna Carter [TeamB] Consultant Software Engineer
John Richardson - 16 Dec 2005 23:29 GMT I completely agree with what you wrote below. But it doesn't quite address what I was asking about originially. I was using the Validation event as an example, but my original post was about how the user can indicate aborting an edit of an individual field, which would then undo the value -> going back to the original previous to the edit. In this case, the *standard* Validation event doesn't apply because the control hasn't lost focus yet. The user is indicating that a mistake was just made, and the original value of the field should be restored. Admittedly, this is very subtle, since it's very similar to just forcing a failed validation procedure.
To continue your Model View Presenter paradigm, it seems useful to have a kind of UserCancelled message to cause the display of the control to be reloaded with previous data; it differentiates a user-initiated cancel from failing a logic test in the Validating handler when the user tries to enter bad data. If this is in fact a good idea, then I guess I'm surprised that the general control interface doesn't provide any implicit methods for this.
<Tab> will change focus. Why not <ESC> to revert to the value before focus. I guess maybe the Form is capturing Esc msgs... Well, either way, I'll have to code what I want myself.
It's been a fun discussion.
> | But, as the user edits a field, the control itself offers a Validation > | event, which is hinting at a Transaction at the control level. So, a [quoted text clipped - 22 lines] > > Joanna Joanna Carter [TeamB] - 17 Dec 2005 15:32 GMT |I completely agree with what you wrote below. But it doesn't quite address | what I was asking about originially. I was using the Validation event as an | example, but my original post was about how the user can indicate aborting | an edit of an individual field, which would then undo the value -> going | back to the original previous to the edit.
| <Tab> will change focus. Why not <ESC> to revert to the value before focus. | I guess maybe the Form is capturing Esc msgs... If you implement IEditableObject in the business object whose properties you are trying to edit, then pressing the Esc key whilst still in the edit will revert the value in the edit to that of the underlying property. Is that what you want ?
| Well, either way, I'll have to code what I want myself. Not necessarily :-)
Joanna
 Signature Joanna Carter [TeamB] Consultant Software Engineer
John Richardson - 20 Dec 2005 03:57 GMT That is precisely what I want, but I realise now that it can only be acheived with databinding, which is not quite what I want, since I don't use databinding where I can avoid it. It's interesting, because online documentation says nothing about relating ESC, IEditableObject, and any generic control. Most google hits discuss the DataGrid, which has several special key behaviours defined. If this works for a textbox, I will be a bit surprised.
Thanks for going the distance.
> |I completely agree with what you wrote below. But it doesn't quite > address [quoted text clipped - 22 lines] > > Joanna Joanna Carter [TeamB] - 20 Dec 2005 09:29 GMT John, I must admit, having gone to the trouble to design a good working BindingList and implementing all the right interfaces to support this behaviour in a DataGridView, I had expected it to work with the edits as well.
Surprise, surprise !! Thanks to you, I now need to delve into the inward parts of the FCL and see why this is not happening; it is a functionality that my client requires as well.
If you should find the answer before I do, please be good enough to drop me a note as well as posting it here. my address is my first name at carterconsulting, the domain is .org.uk.
Joanna
 Signature Joanna Carter [TeamB] Consultant Software Engineer
Joanna Carter [TeamB] - 20 Dec 2005 11:01 GMT John, I just found out the following *horrible* idea to allow for undoing :
private void textBox1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Escape && textBox1.CanUndo) { textBox1.Undo(); textBox1.ClearUndo(); } }
...or you can do something sensible like creating an Extender Provider.
This will get added to your toolbox and you can add one of them to any form; it will hook into the KeyDown event of any and all TExtBoxBase derivatives on the form if you set the UndoOnEsc property of each TextBox to true :
//////////////////////////// using System; using System.ComponentModel; using System.Collections; using System.Windows.Forms;
namespace // your namespace { [ProvideProperty("UndoOnEsc", typeof(TextBoxBase))] public class EditUndoProvider : Component, IExtenderProvider { private class Properties { private bool undoOnEsc = false;
public bool UndoOnEsc { get { return undoOnEsc; } set { undoOnEsc = value; } } }
private Hashtable properties = new Hashtable();
public EditUndoProvider(IContainer parent) { parent.Add(this); }
bool IExtenderProvider.CanExtend(object obj) { return obj is TextBoxBase; }
private Properties EnsurePropertiesExists(object key) { Properties p = (Properties) properties[key];
if (p == null) { p = new Properties();
properties[key] = p; }
return p; }
[Category("Behavior")] [Description("Allows Undo when Esc key is pressed")] [DefaultValue(false)] public bool GetUndoOnEsc(Control c) { return EnsurePropertiesExists(c).UndoOnEsc; }
public void SetUndoOnEsc(Control c, bool value) { EnsurePropertiesExists(c).UndoOnEsc = value;
if (value) c.KeyDown += HandleKeyDown; else c.KeyDown -= HandleKeyDown; }
private void HandleKeyDown(object sender, KeyEventArgs args) { if (!DesignMode) { TextBoxBase control = (TextBoxBase) sender; if (args.KeyCode == Keys.Escape && control.CanUndo) { control.Undo(); control.ClearUndo(); } } } } } ////////////////////////
Joanna
 Signature Joanna Carter [TeamB] Consultant Software Engineer
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|