StrataFrame Forum

Delete an image using PictureEdit

http://forum.strataframe.net/Topic17306.aspx

By Juan Carlos Pazos - 6/24/2008

Hi

I'm using the last version of DevExpress and also last of StrataFrame.

In Visual Basic, I can show and save an image to database using PictureEdit (thanks for all forum posters who has done this first).

But if I delete the image (using the PictureEdit functions) the application has an error.

I saw a solution in C, but I can not implement that in VB.

Waiting for yur valuable help.

Regards

By Guillermo Vilas - 6/24/2008

Hello Juan Carlos,

Can you post a screenshot of the error?
By Juan Carlos Pazos - 6/25/2008

Hi

This is the problem:

The error says: "Can not convert an object type 'System.DBNull' to type 'System.Drawing.Bitmap'." and is in the:

Public Overrides Sub SetValue(ByVal component As Object, ByVal Value As Object)

CType(component, DatosNegocioBO).Logotipo = CType(Value, System.Drawing.Bitmap)

End Sub

As you can see the image shows and saves in the database. This is the configuration for that field:

The field name is "logotipo" is customized as a Custom Data Type: System.Drawing.Bitmap. Serialized is enanble and with Return Alternate on Null with this in the replacement value: New System.Drawing.Bitmap(1, 1)

That generates this in the BO:

''' <summary>

''' Logotipo

''' </summary>

''' <remarks></remarks>

<Browsable(False), _

BusinessFieldDisplayInEditor(), _

Description("Logotipo"), _

DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _

Public Property [Logotipo]() As System.Drawing.Bitmap

Get

Dim loValue As Object

loValue = Me.CurrentRow.Item("Logotipo")

If loValue Is DBNull.Value Then

Return New System.Drawing.Bitmap(1, 1)

Else

Try

Return CType(Me.BinaryFormatter.Deserialize(New MemoryStream(CType(loValue, Byte()))), System.Drawing.Bitmap)

Catch

Return New System.Drawing.Bitmap(1, 1)

End Try

End If

End Get

Set(ByVal value As System.Drawing.Bitmap)

Dim loStream As New MemoryStream()

Me.BinaryFormatter.Serialize(loStream, value)

Me.CurrentRow.Item("Logotipo") = loStream.ToArray()

End Set

End Property

The BindingProperty of the PictureEdit in the form is set to: EditValue that does the trick to show the image.

Regards 

By Dustin Taylor - 6/25/2008

Juan Carlos,

The problem is that you can't serialize a null value "Nothing".  Since you are directly binding to the pictureedit field and using serialization, when you delete the image it tries to save a null to the database but can't since you can't serialize a null.  The simplest way around this would be add custom code in the BO Mapper on that field to handle a null value yourself. However, that is not what I would recommend as the best solution (and I'll tell you why here in a second):

To fix it quickly, just check the "custom code" box for that field in the BO Mapper and add the following to the cutom code page:

 

''' <summary>
''' Logotipo
''' </summary>
''' <remarks></remarks>
<Browsable(False), _
BusinessFieldDisplayInEditor(), _
Description("Logotipo"), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Property [cust_FirstName]() As System.Drawing.Bitmap
   Get
      Try
         Return CType(Me.BinaryFormatter.Deserialize(New MemoryStream(CType(CurrentRow.Item("Logotipo"), Byte()))), System.Drawing.Bitmap)
      Catch
         Return Nothing
      End Try
   End Get
   Set(ByVal value As System.Drawing.Bitmap)
      If value IsNot Nothing Then
         Dim loStream As New MemoryStream()
         Me.BinaryFormatter.Serialize(loStream, value)
         Me.CurrentRow.Item("Logotipo") = loStream.ToArray()
      Else
         Me.CurrentRow.Item("Logotipo") = New Byte() {}
      End If
   End Set
End Property

If you'll notice, all we are doing in the above is checking for a null value ("Nothing") on the set and, if found, setting the value to an empty byte array instead.  This will correct your problem as it stands.

However, the best solution (in my opinion), would be to re-work the way you are handling your PictureEdit alltogether. Basically, remove the binding of this field and instead handle changes to it yourself. When you set the field, pass it directly to the database as a jpeg-formatted byte array. When getting the field, just pull the byte array straight from the database and type it as a jpeg.  The benefit of this is that it would preclude serialization all together.  Using serialization for an image like this bloats the footprint in the database a lot. Talking directly to the database using the raw byte array will be quite a bit faster, and will have a much smaller footprint within your database over time.

By Juan Carlos Pazos - 6/25/2008

Hi

I try this in Custom code but there is a problem.

At the end of the BO there are a propery descriptors, when I put custom code the property descriptors for Logotipo are not created causing forms does not load.

This is what are not created:

''' A PropertyDescriptor class used to Get and Set the value of the Logotipo property."

Regards

By Trent L. Taylor - 6/25/2008

Here is a tip Wink ...GetCustomBindablePropertyDescriptors...you can search the help or this forum and find a LOT of posts on this very procedure.  You will need to override this method on your BO, and add a ReflectionPropertyDescriptor for the custom property.  You can try and check the "Create Descriptor" in the BO Mapper for this property as well and see if it fixes your problem, but if the error persists, just go with the GetCustomBindablePropertyDescriptors method approach.
By Juan Carlos Pazos - 6/25/2008

Hi Trent

Thanks for the tip. I take other path. At the EditValueChanged event I add this code:

If picLogo.EditValue Is Nothing Then

Me.picLogo.EditValue = My.Resources.NoLogo

End If

The NoLogo resource is a Gif with 10 * 10 px.  This way if user cuts or delete the image, always will be an image with no errors.

I understand that there are better ways of do this, but this trick works and let me put my own image if I need to do that.

Thanks for all your time and ideas.

Regards