January 30, 2006, 6:51 pm
When using .NET data binding to bind fields on a Windows form to object properties, the updating of an object property only occurs when the control loses focus. Actually, thats not entirely true – the property is updated during the Validating event of the control. The Validating event occurs when a control loses focus, so that is why it may seem like a control has to lose focus to update the bound property.
The Validating event also occurs in other cases that do not involve a loss of focus:
- user presses “Enter” and thus causes the default button on a form to be clicked
- user uses a shortcut key to press a button on a form
.NET has code to manage these specific cases, so that validation (and thus data binding) works when users interact with forms in those ways. The problem is that the code only really works if the button is on the same form as the field, and that is not always the case.
A common place that a button occurs is on a toolbar. Clicking a toolbar button does not cause a loss of focus, or any validation on the focused form. Thus, a handy “Save” button on a toolbar saves everything but the most recently changed (and still focused) field.
The workaround is simple. In the code that handles the click of a toolbar button, call the Validate method of the active form. This will cause all child controls to validate, thus updating the data binding, and causing the object properties to be correctly updated.
I’ve seen many newsgroup and article posts that suggest calling EndCurrentEdit on the PropertyManager object that is managing the binding. This is a red herring and can cause binding to break – save yourself a headache and simply call the Validate method on the form (or the specific control).
January 30, 2006, 6:25 pm
“A generic error occurred in GDI+” is a common error that you might (will) get when working with .NET code that uses GDI+. Likely tasks that will give this error are:
- Saving an image to a file or stream
- Converting an image to an array of bytes
- Displaying an image
i.e. just about anything While this error seems like it could mean anything, in fact it almost always seems to be related to a single behavior of GDI+:
When an image is loaded from a file or a stream, GDI+ does not always completely read the image – it just does enough to determine the image characteristics — it reads the headers. It then continues to want access to the file or stream, so that it can get at the rest of it when necessary, i.e. when we do one of the aforementioned tasks.
This behavior has several consequences:
- When you load from a stream, you need to keep the stream available until the image is rendered or saved in some way
- When loading an image from a file, the file remains locked until you dispose of the image.
When using image files, Bob Powell suggests the following workaround to allow saving a modified image to the same file:
- Open the image file
- create a temporary in-memory image the same size as the original
- obtain a Graphics object for the temporary image
- Draw the original image onto the temporary one
- dispose of the original
- do any drawing you’d like on the image using the Graphics you have
- Dispose of the Graphics
- Write the temporary file to any filename and any format you please including the same name and format if you wish.
When using streams, you have to keep the stream object around for as long as the image. What worked for me was to keep a reference to the stream as a member variable of the same class that exposed the image member variable.