By Ross L Rooker, Sr.(1) - 5/8/2014
Getting this error:
An exception of type 'MicroFour.StrataFrame.Business.BusinessLayerException' occurred in MicroFour StrataFrame Business.dll but was not handled in user code. Additional information: An error occurred while refreshing the data from field 'tbvo_Groupi.GI_PICTURE' to property 'Image' on control 'pictureBox1.' Are you missing FieldPropertyDescriptor for a custom property?
pictureBox1 is MicroFour.StrataFrame.UI.Windows.Forms.PictureBox
The GI_PICTURE column in a SQL table has the type: varbinary(max).
The BO tbvo_Groupi column GI_PICTURE has a type of System.Byte[]. The Custom Field Properties NULL Value Option is "Don't Allow Nulls". The box for "Use Custom Code" is checked. Here is the custom code:
[Browsable(false), BusinessFieldDisplayInEditor(), Description("GIpicture"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public System.Drawing.Bitmap GI_PICTURE { get { object loValue; loValue = this.CurrentRow["GI_PICTURE"]; if (loValue == DBNull.Value) { return new System.Drawing.Bitmap(1, 1); } else { try { return (System.Drawing.Bitmap)this.BinaryFormatter.Deserialize(new System.IO.MemoryStream((Byte[])loValue)); } catch { return new System.Drawing.Bitmap(1, 1); } } } set { System.IO.MemoryStream loStream = new System.IO.MemoryStream(); this.BinaryFormatter.Serialize(loStream, value); this.CurrentRow["GI_PICTURE"] = loStream.ToArray(); } }
|
By StrataFrame Team - 5/8/2014
Does the exception show an inner exception? Loos like your code is good. The only place I can see that it would fail is if the business object is empty, then when you access CurrentRow, it will throw an exception telling you the count is 0 and the row index is -1. If the image was improperly serialized, then it would return a 1x1 BMP, so that's not it. Also, can you put a breakpoint in the property and see what it's doing? You could also set VS to break when an exception is thrown. Debug -> Exceptions -> Checkmark Common Language Runtime exceptions.
|
By Ross L Rooker, Sr.(1) - 5/8/2014
Here is the result:
|
By Ross L Rooker, Sr.(1) - 5/8/2014
Not sure what a Field Property Descriptor is, but here is debug info on the GI_PICTURE column:
|
By StrataFrame Team - 5/8/2014
Ah, just remembered that there is a checkbox in the customization dialog in the BOMapper that needs to be checked. It tells the BOMapper to create the property descriptor for the custom property. Since you can use the custom code to snuff the property creation, we don't put out a property descriptor by default.
|
By Ross L Rooker, Sr.(1) - 5/8/2014
I checked the Create Descriptor box and get this error when I compile the BO:
|
By StrataFrame Team - 5/8/2014
Ah, the type has changed. Uncheck the box and you will need to override the GetCustomBindablePropertyDescriptors method in the main code file of the BO:
using MicroFour.StrataFrame.Business; protected override FieldPropertyDescriptor[] GetCustomBindablePropertyDescriptors() { List<FieldPropertyDescriptor> r = new List<FieldPropertyDescriptor>(); r.Add(new ReflectionPropertyDescriptor("GI_PICTURE", typeof(BOType))); //-- Return results return r.ToArray(); } Replace the "BOType" with the type of your BO.
|
By Ross L Rooker, Sr.(1) - 5/8/2014
One last issue. If the GI_PICTURE column is null, the code fails with a null:
protected override FieldPropertyDescriptor[] GetCustomBindablePropertyDescriptors() { List<FieldPropertyDescriptor> r = new List<FieldPropertyDescriptor>();
r.Add(new ReflectionPropertyDescriptor("GI_PICTURE", typeof(System.Byte[])));
//-- Return results return r.ToArray(); }
Not sure if I need to wrap in a try/catch and in the catch insert some code. Or in the BO Mapper insert some code if null.
|
By StrataFrame Team - 5/8/2014
Oh, the typeof needs to be the BO type, not the type of the property.
typeof(tbvo_GROUPI) It's returning null because that property doesn't exist on a byte array.
|
By Ross L Rooker, Sr.(1) - 5/8/2014
absolutely awesome. Worked like a charm.
|
By Ross L Rooker, Sr.(1) - 5/9/2014
I dragged the MicroFour.StrataFrame.UI.Windows.Forms.PictureBox control on my form and set the column GI_PICTURE as shown below.
See the error I am getting at the far bottom.
Here is the FieldPropertyDescriptor in the BO:
Here is how the column is set up in the backend SQL Database:
Here is the BO Mapper for the GI_PICTURE column:
Here is the Custom Code for the GI_PICTURE:
Here is more detail of the error that is causing the GI_PICTURE to not display:
|
By StrataFrame Team - 5/9/2014
How was the data put into the field in the first place? If the BinaryFormatter cannot deserialize the object, then I'm guessing that it's the raw bitmap data, right? In that case, you need to change your custom property to the following:
public System.Drawing.Bitmap GI_PICTURE { get { object value = this.CurrentRow["GI_PICTURE"]; if(value is byte[]) { return new System.Drawing.Bitmap(new System.IO.MemoryStream((byte[])value)); } else { return new System.Drawing.Bitmap(1, 1); } } set { System.IO.MemoryStream ms = new System.IO.MemoryStream(); value.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); this.CurrentRow["GI_PICTURE"] = ms.ToArray(); } } You may need to change the System.Drawing.Imaging.ImageFormat.Bmp to Jpeg or whatever format the data is stored in.
|
By Ross L Rooker, Sr.(1) - 5/9/2014
YES!!!! Perfect.
|
By StrataFrame Team - 5/9/2014
Awesome. Glad it's working for you
|
By Ross L Rooker, Sr.(1) - 5/9/2014
One last question. On my form where the picture displays, I have a button to load a different picture into the PictureBox and that works. But when I SAVE it doesn't save and I get no error. Keeps the original picture. Here is the code you provided that I used:
[Browsable(false), BusinessFieldDisplayInEditor(), Description("GIpicture"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public System.Drawing.Bitmap GI_PICTURE { get { object value = this.CurrentRow["GI_PICTURE"]; if(value is byte[]) { return new System.Drawing.Bitmap(new System.IO.MemoryStream((byte[])value)); } else { return new System.Drawing.Bitmap(1, 1); } } set { System.IO.MemoryStream ms = new System.IO.MemoryStream(); value.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); this.CurrentRow["GI_PICTURE"] = ms.ToArray(); } }
|
By StrataFrame Team - 5/9/2014
If you put a breakpoint there, is ms.Length > 0 after the call to value.Save()? Does the BO go dirty after the call to this.CurrentRow['field'] = ms.ToArray()?
|
By Ross L Rooker, Sr.(1) - 5/9/2014
On SAVE the SET does not get executed. Not sure why?
[Browsable(false), BusinessFieldDisplayInEditor(), Description("GIpicture"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public System.Drawing.Bitmap GI_PICTURE { get { object value = this.CurrentRow["GI_PICTURE"]; if (value is byte[]) { return new System.Drawing.Bitmap(new System.IO.MemoryStream((byte[])value)); } else { return new System.Drawing.Bitmap(1, 1); } } set { System.IO.MemoryStream ms = new System.IO.MemoryStream(); value.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); this.CurrentRow["GI_PICTURE"] = ms.ToArray(); } }
|
By StrataFrame Team - 5/9/2014
The set of that property won't get called when you call Save() on the BO. It will only get called if you set the property to a new value, like this:
bo.GI_PICTURE = newBmp; How are you trying to set the new value back to that property?
|
By Ross L Rooker, Sr.(1) - 5/9/2014
I thought just binding the PictureBox to the GI_PICTURE column would handle it automatically like a textbox. What I did was what you indicated above:
On the button where the user would click LOAD and selected a file (jpg, etc) after the user selected the file I added:
tbvo_Groupi.GI_PICTURE = new System.Drawing.Bitmap(new System.IO.MemoryStream(ConvertImageToByteArray(pictureBox1.Image, System.Drawing.Imaging.ImageFormat.Jpeg), false));
Added the "ConvertImageToByteArray":
private byte[] ConvertImageToByteArray(System.Drawing.Image imageToConvert, System.Drawing.Imaging.ImageFormat formatOfImage) { byte[] Ret; try { using (MemoryStream ms = new MemoryStream()) { imageToConvert.Save(ms, formatOfImage); Ret = ms.ToArray(); } } catch (Exception) { throw; } return Ret; }
This works beautifully.
|