Project Logs: Frosty Mug, Part 1

Genesis

A seemingly simple project, this is one I’ve been thinking of making for a long time now. Mostly because I had acquired a couple of thermoelctric cooling elements and wanted to use them for something. That, coupled with a desire to keep my soda cold while writing code, pushed me into this challenge. Now, while in theory, this device is pretty simple. In fact, I’m pretty sure a few already exist that I could probably just buy, but there is no fun in that. The challenge comes in that thermoelectric coolers suck. They eat power, are terribly inefficient compared to compressor based cooling systems, and generate a lot of waste heat. In fact, I own a thermoelectric powered travel cooler and at best it could maybe keep stuff slightly colder than a regular cooler. It certainly couldn’t chill anything. However, they are solid state and small, that is if you don’t count the heat sink and fan required. The challenge is not just to build one, but build one that actually works.

Criteria for Success

A good project always needs a sound criteria for reaching success. Otherwise, how will you know when you’ve succeeded? In this case I’m going to set my goals rather high. The primary goal will to be to keep a 20oz plastic soda bottle ice cold, for an indefinite period, at average room temperature. I’ll set the standard for ice cold as 35 degrees Fahrenheit, about the temperature of the average refrigerator. Once I feel I’m close to the goal, I’ll probably have to design a test rig to get an accurate measurement. That’s a pretty stiff requirement, but to make it easier, I will focus on keeping a cold soda cold, rather than trying to chill a warm one. Another tough aspect is using a plastic bottle. Bottles tend to not have a lot of surface area that contacts the surface they are on, and the plastic probably won’t conduct heat very well. As an alternative goal, I can attempt to do the same with a 12 ounce aluminum can. Presumably a metal can would get better thermal transfer from the cooling surface, but at the same time would leak more heat into the air than the plastic bottle would.

Experimentation

Stop the World and Melt with Me, Build #1

My first experiment will make use of a cooling element I aquired some time ago from All Electronics. Here’s the specsheet they provided. The basic operation of these modules is to create a temperature differential between the hot side and the cold side. The spec on this module give a max temperature delta of 79 C (174 F). I wasn’t quite sure how to read the graphs on the sheet, but I figure at 12 volts I could hope for a 60 – 70 C (140 -158 F) delta. Now, that temperature difference, I assume, is from side to side of the element. So given the temperature gradient from the element surfaces to the surfaces I’ll be measuring, I probably won’t see that big of a delta.

Supplies:

  • Power Supply, 12 volt 10 amp, brick style (for monitor or TV) via Ebay, $12.99 USD.
  • Aluminum Plate, 3 inch diameter, 1/4 inch thick, via Ebay, $13.15 for 2.
  • Long machine screws and nuts, #10 x 1.5 inch, via TrueValue, $3.58 for 4 bolts and 14 nuts.
  • Printed parts, via myself, (STL Files: Top, Bottom)
  • Heatsink, via Newegg, $11.99
  • Thermoelectric cooler, 40mm X 40mm, 80 Watt max, via AllElectronics, $14.75.

Here’s what it looked like:

Unfortunately, this build had a couple issues from the start, which is a shame since it was rather small and quiet. First and foremost, the little chip set cooler heat sink/fan combo was ridiculously undersized. While it did cool the top side, the bottom side quickly rose to a fairly high temperature around 150 Fahrenheit. This not only above the max temperature rating for the element, but it also deformed the PLA frame.

With the high temperature on the hot side, and the heat capacity of the top aluminum plate, I was only getting slightly less than 50 F on the plate. As a side note, I was having a difficult time measuring the temperature of the plate with my IR thermometer, as the reflectivity of the plate caused it to just return the room temperature. I finally figured out that a small piece of tape on the surface would give me the ability to measure it better. Since the aluminum discs I bought came in quantities of 2, I repeated the experiment with the extra disc between the element and the heat sink. This made it work better for a short period, but the heat quickly built up and the same situation occurred. The simple conclusion was that my heat-sinking was insufficient, and that a larger heat sink would be required to whisk away all the waste heat fast enough to keep the element working effectively.

Now I did try the same setup a second time with a different element that I also had. I also bought this from All Electronics a long time ago, but unfortunately they don’t sell that unit any more, so the specs are unknown. The only things I know is that the unit itself is smaller, 30mm square as compared the the other unit at 40mm square, and the smaller unit drew about 2.5 A when first powered on as opposed to about 5.5 A that the other unit drew at 12 V. This configuration was at least stable, the hot side topped out at about 110 F, and the top disc dropped to about 45 F. I would have expected a higher temperature difference to have developed, but I think the smaller unit lacked the cooling power to get the 1/4 inch thick disc any colder.

Build #2

Armed with the knowledge that I was not sinking enough heat, I got a slightly larger, cheap CPU heat sink, about $9.99 from NewEgg. I also purchased two more of the 3 inch diameter aluminum discs from eBay, just in case. After a few experiments, I was having the same issue with the large cooler, heat would build up extremely fast on the hot side, limiting the temperature drop on the top side. I also had the same issue with the small cooler, not being able to drop the temperature of the disc very well. Although testing the small unit on the new heatsink, without the top disc revealed that the units were reaching a good temperature, just below 30 F, cold enough to form a bit of frost on the top.

I experimented more with the large unit, using the 3 spare discs in increase the mass of the heat sink. Although I used quite a bit of thermal paste, I feel that the effectiveness was limited by the heat transfer between the discs. But it did seem to work better.

As you can see, I didn’t bother making a frame for this experiment, I may have been a bit premature on printing a frame for the first build. With this setup, it initially worked fairly well with the big element, dropping the top plate temperature down to about 25 F. This seemed promising, but the hot side rose to around 140 F after
5 minutes or so, which brought the top disc up to around 40 F. I shut it down around then, because i didn’t know when or if it would achieve a stasis. I did test this with the smaller cooler, which did reach a static state, just under 100 F on the hot side, and about 50 F on the cold disc. I removed the top plate to measure the unit directly, and showed about 30 F on the top of the unit. A similar direct measurement of the top of the larger unit showed an initial temperature of -10 F, again that quickly rose with the heat buildup on the other side.

General Observations

While part 1 of this project has not left us with a unit that can meet the project goal, we have learned a lot that will hopefully lead to that. Let’s review.

  1. The large 40mm square, 80 Watt max cooling power element should have the cooling power required for this application, it demonstrated the ability to quickly cool the aluminum disc, and showed a fairly high temperature delta.
  2. The heatsink needs to be larger to support the large cooling element. It generated tons of waste heat, that all heat sink configurations in the experiment failed to dissipate quickly enough to reach a static state.
  3. The small cooling element, of unknown spec, did not have the cooling power required to keep the aluminum disc at a low enough temperature for the application.
  4. All the tested heasink configurations were enough to bring the small cooling element to a static state.

Conclusions

  1. The large cooling element needs to be tested with larger, more effective heat sinks.
  2. The small cooling element will not be used in further experiments.
  3. I should explore different cooling elements to use.

That’s it for now. Hopefully in the next installment I can demonstrate a working unit!


Posted in Electronics, Uncategorized | Tagged , , | Leave a comment

3D Printer ATX Power Supply Fix

Recently, I had the pleasure of putting together my first 3D printer, a design by the RepRap project.

One of the more important aspects of the build is acquiring a power capable of driving at least 16 amps at about 12 volts. The cheapest solution usually used, is the humble ATX power supply. Mass produced for the desktop PC market, they can supply high current at common voltages, and are available everywhere. The ATX supply is easily converted to power the RepRap hardware, and that info is covered on their wiki. I quickly found a supply off of NewEgg, specifically, this one. Featuring 25 amps of output on the 12 volt rail, and only $20, this fit the bill quite nicely. However, once I got everything hooked up and did a few test prints, I had one slight problem. The power supply would, seemingly randomly, shut itself off, ruining my print.

The first attempts to correct this followed advice on the wiki and in many forum posts. The recommendation was to put a significant load, 1 or 2 amps, on the 5 volt rail of the power supply. The theory goes that, depending on how the supply was designed, it expects most of the load to go to the 5 volt rail, as it would if it was hooked to the computer system it was designed to power. This can cause significant voltage drop on the 12 volt rail when its loaded without load on the 5 volt rail, causing the supply’s internal protection circuit to shut down the supply. Following this advice, I hooked a couple large 1 ohm power resistors in series, glued them to some aluminum head sinks, to give a nice 2.5 amp load for the 5 volt rail. Unfortunately, this failed to solve the issue.

I decided to Google around to see how easy it would be to simply disable the safety features of the power supply, and I found an interesting article. Interestingly, these guys were powering 12 volt audio amplifiers at high current, and running into the same problem as me. Reading the article revealed that shutdown protection was controlled by a single IC inside the supply, and could easily be controlled by grounding some pins. Now, the supply they were modding didn’t have the control chip as the supply I had, and that led me to their source article, here, and the datasheet for the chip I found in my supply.

The final fix took several iterations to get right. The simple fix in the article, grounding pin #4 to disable all under voltage protection for all rails, just didn’t work for me. The supply still shut itself down. After reading into the datasheet, I learned that the IC monitors the voltages on the main rails, 3.3, 5, and 12v. It monitors these voltages through pins 1,2, and 3. The datasheet revealed that simply grounding these pins disables the monitoring for both under and over voltage conditions, which should prevent it from shutting off spontaneously. Normally, not what you would want, but some aspect of the printer, the motors or the heat bed, must have been producing voltage spikes that were accidentally tripping this protection. This change turned out to be pretty easy, since the datasheet showed that pin #5 was ground, so it was just a matter of connecting pins 1,2,3,4, and 5 together, and cutting the traces to pins 1-4. Once I did this, viola! My printer has been working without shutting down since.

Here’s a view of the top of the control IC on the ATX single sided PCB.

Here is a view of the changes I made. As you can see, I just used a sharp pointy object to scratch away at the PCB till I was sure the traces leading to pins 1-4 were all cut. I had to add the blue wire, because the one trace ran past the pin and to another spot. The red wire was coming off the ground pin to pin #4. After that I decided just to solder bridge to the rest of the pins.


Posted in Electronics | Tagged , , , | Leave a comment

Lambda Expressions for Easy Custom Sorts

If you’re like me, then you like to experiment with new and different ways to do the usual programming tasks that you do. Perhaps its just a reaction to the boredom of always doing things the same way. Sometimes its an attempt to make the easy but time consuming tasks faster. Often is in a search for better looking, more abstract code. I like to think of it as a learning opportunity. The other day I was playing with sorting a list of objects. There are build in ways to do this in the List(Of T) class, so I though I would experiment with the different overloads of the List(Of T).Sort() method. While what is provided by the .NET Framework is adequate to make clean code, I played around anyways because you never know when you will run into something that doesn’t give you a clean solution out of the box. So just in case, its good to add more tools to your mental utility belt, at least that’s what I tell myself so it doesn’t feel like I’m wasting time.

For sorting an object based on an arbitrary property, the Sort() is not helpful as you cannot specify how the comparison is to be made. So that takes us to the first overload, Sort(IComparer(Of T)). This method is probably too cumbersome for standard adhoc and one time sorts that you may have to do. It requires that you pass it an instance of a class that implements IComparer(Of T), and the Compare method of that class will define your comparisons. One of my favorite features in .NET is generic types, as it increases code reuse substantially. So, why not make a generic class that takes a lambda function in the constructor to use as the comparison?


Public Class GenericCompare(Of T)
    Implements System.Collections.Generic.IComparer(Of T)

    Dim Func As Func(Of T, T, Integer)

    Public Sub New(ByVal Func As Func(Of T, T, Integer))
        Me.Func = Func
    End Sub

    Public Function Compare(ByVal x As T, ByVal y As T) As Integer Implements System.Collections.Generic.IComparer(Of T).Compare
        Return Func(x, y)
    End Function

End Class

Assuming a general object to sort like this one:


Public Class SomeObject

    Public Property Name As String

    Public Property Value1 As String

    Public Property Value2 As String

End Class

That will make our sort look like this:


        'Sort with custom compare
        Items.Sort(New GenericCompare(Of SomeObject)(Function(x, y)
                                                         If x.Name > y.Name Then
                                                             Return 1
                                                         ElseIf x.Name < y.Name Then
                                                             Return -1
                                                         Else
                                                             Return 0
                                                         End If
                                                     End Function))

The above uses a long implementation for the comparison, which could be used for customizing the sort order or sorting on multiple fields if needed. If you just want a basic string comparison of one property, you can shorten the above to this:


        'Or, sort with default string compare, one liner
        Items.Sort(New GenericCompare(Of SomeObject)(Function(x, y) String.Compare(x.Name, y.Name)))

Going crazy with this concept, you could even introduce an extension method to add another overload to Sort().


Public Module ExtensionMethods

    <System.Runtime.CompilerServices.Extension()>
    Public Sub Sort(Of T)(ByVal List As List(Of T), ByVal Func As Func(Of T, T, Integer))
        List.Sort(New GenericCompare(Of T)(Func))
    End Sub

End Module

Then your sort becomes this:


        'Or with the extension method
        Items.Sort(Function(x As SomeObject, y As SomeObject) String.Compare(x.Name, y.Name))

I’m not sure why exactly, but if you notice in this usage, I had to specify the type for the x, y arguments. Unlike the last example, the compiler isn’t able to infer the type of the arguments.

Now, if you are looking at the different overloads for the Sort method, you may have notice that there is another overload that does basically what we just created. List(Of T).Sort(Comparison(Of T) takes a delegate to a function. So in this usage you would just have to create a function in your code that follows the Comparison(Of T) delegate. As we know however, a lambda expression can be used anywhere a delegate is expected, so we can shorten this up into a one-liner as well.


        Items.Sort(New Comparison(Of SomeObject)(Function(x As SomeObject, y As SomeObject) String.Compare(x.Name, y.Name)))

Although, the New Comparison(Of SomeObject)(...) is actually not necessary, and the use of this override can be shortened to the equivalent of the extension method example above.


Items.Sort(Function(x As SomeObject, y As SomeObject) String.Compare(x.Name, y.Name))

OK, so I played around a lot with the List(Of T).Sort methods and concluded that sorting a list of objects on an arbitrary property is pretty easy, and that .NET provides an overload that accepts a delegate or lambda for the comparison. So did I waste my time inventing that first method? Possibly, but I did prove to myself that you can create a generic class that can be made to accept lambdas that define its behavior. I can safely say I learned something and added another technique to the old toolbox, so in my onion a great use of time.


Posted in Uncategorized, VB.Net | Tagged , , , | Leave a comment

On Accessing Access from 64 Bit

One skill they say is needed for software development is problem solving, and as a developer myself I know this to be true. It often seems like not a day will go by without encountering something outside of the original plan. Just the other day I was testing an application, which simply reads some data from a MS Access database. The database is part of a purchased software product, so I don’t really have any choice in the matter, it must be Access. Then up pops an exception The 'Microsoft.Jet.OLEDB.4.0' provider is not registered on the local machine.

Well some internet research quickly found that the default Jet database driver is not 64 bit compatible. The official resolution? Force your application to be 32 bit and all will be well. Well, not today. Although I hate leaving such decisions up dumb incompatibility issues, in this case I couldn’t make my app 32 bit. The application is an add-on extension to AutoCAD, which, if your running 64 bit windows, will only install as 64 bit. That means that any assemblies it loads, like mine, must also run 64 bit.

So, here I though I was up that darn creek again without my paddle. But low and behold I found my original research was a little dated, there was a new 64 bit driver that could be used for Access databases. It turns out, that even though Microsoft really wanted to steer developers away from using Access in favor of SQL Express, they had to make a driver so that the MS Office suite could be 64 bit. Ok, cool. So I download the new driver, but of course, it doesn’t install. It complains that I must first uninstall my 32 bit version of Office before installing the driver. Ok, I definitely don’t want to go down this road, because not only does it mean making sure that this new driver gets installed on the users PC, but that the correct version of Office is on there as well.

Well, there I sat, convinced that this would either not work or be one of those things I regret doing much later. Then a little inspiration. I though, maybe I just need a separate assembly that can run 32 bit? Well that’s not possible, the 32/64 bit decision is made for the whole process, not just an assembly. It would have to be a separate executable.
I started to feel good about this, a separate ‘proxy’ executable to interact with access for me. The interprocess communication wouldn’t be bad, I would just have to send it SQL statements and it could send me back the results as a DataTable. The DataTable object has its own ReadXML and WriteXML functions, so the matter of moving the object would be simple.

Ok, so a separate executable. That would mean another project in my solution and in source control. It would also have to get deployed with the client with a known location so it can be started when its needed. Not really that big of a hurdle, but I wanted to try for something else anyways. More internet research turned up some example of using the CodeDOMProvider class to compile and emit an executable file. I liked that concept, create the executable on demand from a short piece of code. Wrap all this up in a single class and I’m happy.

First thing to do was write the proxy code. I really only needed two operations from the database. The ‘Execute Scalar’ option to return a singe value, and an option to fill a DataTable object with results from an query. If I used the System.Diagnostics.Process to start the proxy process, I could read and write to the processes standard input and standard output. That way the proxy could use the Console.In and Console.Out streams to handle its communication with the client process.

So I pass the proxy the connection string on the command line, so it can create a connection object to be used later. Then it reads from standard input. I will send it commands and end the commands with the null character. Once it reads the command, either 'GetDT', 'Scalar', or 'Die', it then looks for the query to written to standard input, again terminated with the null character. It executes the query, then either writes the singe value to standard out for scalar, or it writes the XML representation of the DataTable object. The calling process reads the result and we are done.

Now the client class was designed to be created, used, and then closed. The constructor, which also contains the source code to the proxy as a simple string constant, compiles the proxy code and generates the executable file. The constructor then runs the executable, saving the Process object so the standard in and out can be used later. The object then defines a function for each command it can run in the proxy. The function sends the commands and retrieves the result from the proxy's standard output. When you are done using the object, simply call the Close method to send the proxy the 'Die' command. When the proxy receives this command the process exists.

See the full class code below:

Imports System.CodeDom.Compiler

Public Class Access64Bridge

    Private Proc As Process

    Public Sub New(ByVal ConnectionString)

        'just use the temp folder for the exe location
        Dim output As String = My.Computer.FileSystem.SpecialDirectories.Temp & "\Access64Bridge.exe"

        Dim CDP As CodeDomProvider = CodeDomProvider.CreateProvider("VB")
        Dim params As New CompilerParameters
        params.OutputAssembly = output
        params.GenerateExecutable = True
        'Compiler options, most important are x86 flag and winexe
        '/target:winexe doesn't show a console window
        params.CompilerOptions &= "/platform:x86 /optioninfer /optionstrict- /target:winexe"
        'Add references required by code
        params.ReferencedAssemblies.Add("System.Data.dll")
        params.ReferencedAssemblies.Add("System.Xml.dll")
        params.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")

        'CDATA xml trick from the internet, good way to do multiline
        'string literal like some other languages allow
        Dim Source As String = <![CDATA[
        Imports System
        Imports System.Data
        Imports Microsoft.VisualBasic

        Class Test
        Public Shared Sub Main(ByVal args() As String)
            Try
                Dim connstr As String = args(0)
            Dim conn = New
                OleDb.OleDbConnection(connstr)

                Do
                    'Get Command
                    Dim Comm As String = ReadInputValue()
                    Select Case Comm
                        Case "GetDT"
                            'Next thing in is the SQL
                            Dim SQL As String = ReadInputValue()

                            Dim DT As DataTable = New DataTable()
                            Dim DAObjOLE As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter
                            Dim CommandObj As New OleDb.OleDbCommand(SQL, conn)

                            conn.Open()
                            DAObjOLE.SelectCommand = CommandObj
                            DAObjOLE.Fill(DT)
                            conn.Close()

                            DT.TableName = "Output"
                            'Serialize data table to the
                            output()
                            DT.WriteXml(Console.Out,
                            XmlWriteMode.WriteSchema)
                            'End with the null char
                            Console.Out.Write(vbNullChar)
                        Case "Scalar"
                            'Next thing in is the SQL
                            Dim SQL As String = ReadInputValue()
                            Dim CommandObj As New OleDb.OleDbCommand(SQL, conn)

                            conn.Open()
                            Dim Value As Object = CommandObj.ExecuteScalar
                            conn.Close()

                            Console.Out.Write(Value.ToString)
                            Console.Out.Write(vbNullChar)
                        Case "Die"
                            Return
                        Case Else
                            'Unrecognized command, host possibly is gone, just end
                            Return

                    End Select

                Loop
            Catch ex As Exception
                MsgBox("Access 64 to 32 bit Bridge: " &
                ex.Message & ex.StackTrace)
            End Try
        End Sub

        Public Shared Function ReadInputValue() As String
            Dim Value As New Text.StringBuilder
            Dim ch As Integer = Console.In.Read
            While ch <> 0 And ch <> -1
                Value.Append(Chr(ch))
                ch = Console.In.Read
            End While
            Return Value.ToString
        End Function
    End Class

        ]]>.Value

        Dim Result As CompilerResults = CDP.CompileAssemblyFromSource(params, Source)
        Dim X As New System.Diagnostics.ProcessStartInfo
        'Must redirecte standard in and out so we can use it
        X.RedirectStandardOutput = True
        X.RedirectStandardInput = True
        'Path of executable to run
        X.FileName = output
        'Required for redirection
        X.UseShellExecute = False
        'Connection string surrounded by double quotes so it comes
        'into the proxy as a single argument
        X.Arguments = """" & ConnectionString & """"
        'Start Process
        Proc = Process.Start(X)

    End Sub

    ''' <summary>
    ''' Reads a value from the access bridge program
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ReadValue() As String
        Dim Value As New Text.StringBuilder
        Dim ch As Integer = Proc.StandardOutput.Read
        'use null termniated messages, -1 means the stream is dead
        While ch <> 0 And ch <> -1
            Value.Append(Chr(ch))
            ch = Proc.StandardOutput.Read
        End While
        Return Value.ToString
    End Function

    ''' <summary>
    ''' Runs sql and returns the first result
    ''' </summary>
    ''' <param name="Sql"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ExecuteScalar(ByVal Sql As String) As Object
        'Command
        Proc.StandardInput.Write("Scalar")
        'Null terminate
        Proc.StandardInput.Write(vbNullChar)
        'Sql
        Proc.StandardInput.Write(Sql)
        'Null termniate
        Proc.StandardInput.Write(vbNullChar)

        Return ReadValue()
    End Function

    ''' <summary>
    ''' Executes the SQL on the bridge and returns the resulting DataTable
    ''' </summary>
    ''' <param name="Sql"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CreateDT(ByVal Sql As String) As DataTable
        'Command
        Proc.StandardInput.Write("GetDT")
        'Null terminate
        Proc.StandardInput.Write(vbNullChar)
        'Sql
        Proc.StandardInput.Write(Sql)
        'Null termniate
        Proc.StandardInput.Write(vbNullChar)

        Dim Value = ReadValue()
        Dim DT As New DataTable
        DT.ReadXml(New IO.StringReader(Value))
        'Accept changes else all rows will be new
        'New rows are removed from the collection when deleted
        DT.AcceptChanges()
        Return DT
    End Function

    Public Sub Close()
        'Command
        Proc.StandardInput.Write("Die")
        'Null terminate
        Proc.StandardInput.Write(vbNullChar)
    End Sub
End Class

You never know what your going to have to do to get the job done.


Posted in VB.Net | Tagged , , , | 1 Comment

Form/Class Mapping With Custom Provider Control

In my last article, I talked a little bit about taking time to program for yourself. The example used was a drop-down list control that automatically filled itself from an enumeration. Today, we will be looking at the process of filling a form from, and copying data back to, a class. A typical situation for software that deals with user input. Whether its data collection, sales order entry, or whatever, the standard CRUD (create,read,update,delete) theme is repeated over and over again. With anything that is repeated over and over, it can, and probably should be automated. The following is a simplified example of how to replace the process of manually ‘gluing’ your forms controls to the underlying class object.

I’ve explored the process of doing this before in other projects. The original scheme was to create a base class that all other controls/forms would inherit from that contained all the generic code for filling the controls and updating the class. Although this worked quite well, you can always learn something from exploring a new approach. So, instead of using a universal base control/form, we will instead be using a Custom Provider Control. To explain, this is similar to how the ToolTip component works. It provides a service to the form/control its placed on, and adds a property to each control in the property designer. So our control will provide the service of filling the form with class data, and updating the class data when the user changes what’s on the form.

First things first, we need to create or provider control. If you read the linked article above, you see that we just have to create a new class that inherits from System.ComponentModel.Component, and implements the System.ComponentModel.IExtenderProvider interface. It also needs to have a System.ComponentModel.ProvideProperty attribute, which give the property to be added to controls in the property wizard and also give a control type filter.

<System.ComponentModel.ProvideProperty("PropertyName", GetType(Control))>
Public Class ControlMapper
    Inherits System.ComponentModel.Component
    Implements System.ComponentModel.IExtenderProvider

The property name we give to the ProvideProperty attribute is "PropertyName", since what we are mapping our controls to are public properties of a class. The type filter we give it is just Control, since we could bind a property to almost any type of control we can code for. That leads us to the implementation of the IExtenderProvider interface, which contains only one method, CanExtend. CanExtend is called for any control in the form and we return True if our class will extend it, or False if it will not.

    Public Function CanExtend(ByVal extendee As Object) As Boolean Implements System.ComponentModel.IExtenderProvider.CanExtend
        If extendee.GetType Is GetType(TextBox) Then
            Return True
        Else
            Return False
        End If
    End Function

For simplicity of the example, we will only deal with text boxes. I'll leave it as an exercise for you to extend the class to handle other controls like combo boxes, picture boxes, calendars, etc. Now, the next thing that needs to be created is a Get and Set function for the property name we gave to the ProvideProperty attribute, in the format of GetPropertyName and SetPropertyName. These functions will use a private member Mapped which is an instance of Dictionary(of Control, String). This local will track the controls that are being associated to the provider and the property name that was set in the designer. We also set up and event handler when the property is set, so that we can update the forms class when the text is changed by the user.


    Public Function GetPropertyName(ByVal myControl As Control) As String
        'Get property name based on control, return empty string if not found
        If Mapped.ContainsKey(myControl) Then
            Return Mapped.Item(myControl)
        Else
            Return ""
        End If
    End Function

    Public Sub SetPropertyName(ByVal myControl As Control, ByVal value As String)
        'Add property/control pair to dictionary
        If Mapped.ContainsKey(myControl) Then
            Mapped.Item(myControl) = value
        Else
            Mapped.Add(myControl, value)
        End If
        'Add event handler for control type
        If myControl.GetType() Is GetType(TextBox) Then
            Dim tb As TextBox = myControl
            AddHandler tb.TextChanged, AddressOf Me.TextChanged
        End If
    End Sub

Now, we need to add a public property to the provider itself, so the form using it can give it a pointer to the class object that the form is editing.

Public Property FormObject As Object

And we will add a private field, to mark when we are filling the form. This will server to let us ignore events while we populate controls with class object data.

Dim Filling As Boolean = False

Now, the first thing we have to do before we edit data, is that we must load it to be edited. So a method is needed to fill all the associated controls with the value of the property they were mapped to. We first loop through the KeyValuePair(of Control, String) that are stored in our Mapped dictionary, this gives us the control object and the name of the property it is bound to.

Dim Cntl As Control = item.Key
Dim PropertyName As String = item.Value

Then, using reflection, we can retrieve the PropertyInfo for the property name and use it to get the value from the class object.

Dim Prop = FormObject.GetType().GetProperty(PropertyName)
Value = Prop.GetValue(FormObject, Nothing)

Here's the complete fill method, complete with null checks, etc.

    Public Sub FillFromClass()
        'Check for null
        If FormObject IsNot Nothing Then
            Try
                'Set filing flag, use try...finally structure to
                'ensure the flag is always turned off
                Filling = True
                'Loop through all handled controls
                For Each item In Mapped
                    'Get control on property name from dictionary item
                    Dim Cntl As Control = item.Key
                    Dim PropertyName As String = item.Value
                    'Get value from class
                    Dim Value As Object
                    'Get reflection property
                    Dim Prop = FormObject.GetType().GetProperty(PropertyName)
                    'Check null
                    If Prop IsNot Nothing Then
                        'get property value
                        Value = Prop.GetValue(FormObject, Nothing)
                        'Set value according to control type
                        If Cntl.GetType() Is GetType(TextBox) Then
                            'Set text property for text boxes
                            Dim TB As TextBox = Cntl
                            TB.Text = Value
                            'Done!
                        End If
                    End If
                Next
            Finally
                Filling = False
            End Try
        End If
    End Sub

As you may have seen in the SetPropertyName method, we are adding an event handler to the TextChanged event of the text box. This event will handle updating the FormObject with the value from the modified control. We can use the GetPropertyName function to get the name of the property the control is bound to so that we can update FormObject using reflection.

    Private Sub TextChanged(ByVal sender As Control, ByVal e As EventArgs)
        'Check for DesingMode
        If Not DesignMode Then
            'Check if the control is being filled
            If Not Filling Then
                'Check for null
                If FormObject IsNot Nothing Then
                    'Get the name of the property bound to control
                    Dim PropetyName = GetPropertyName(sender)
                    'Check if found
                    If PropetyName <> "" Then
                        'Get property using reflection
                        Dim Prop = FormObject.GetType().GetProperty(PropetyName)
                        'Check null
                        If Prop IsNot Nothing Then
                            'Get value based on control type
                            Dim Value As Object
                            If sender.GetType() Is GetType(TextBox) Then
                                'Get text property
                                Value = CType(sender, TextBox).Text
                            Else
                                'Unsupported control type
                                Return
                            End If
                            'Set the value of the class to the new value
                            Prop.SetValue(FormObject, Value, Nothing)
                            'All done!
                        End If
                    End If
                End If
            End If
        End If
    End Sub

That completes our provider. Here's the complete code.


<System.ComponentModel.ProvideProperty("PropertyName", GetType(Control))>
Public Class ControlMapper
    Inherits System.ComponentModel.Component
    Implements System.ComponentModel.IExtenderProvider

    ''' <summary>
    ''' Dictionary to hold control/property mapping
    ''' </summary>
    ''' <remarks></remarks>
    Dim Mapped As Dictionary(Of Control, String)

    Public Sub New()
        'Instantiate the dictionary
        Mapped = New Dictionary(Of Control, String)
    End Sub

    ''' <summary>
    ''' Get function used by the ProvideProperty attribute
    ''' </summary>
    ''' <param name="myControl"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetPropertyName(ByVal myControl As Control) As String
        'Get property name based on control, return empty string if not found
        If Mapped.ContainsKey(myControl) Then
            Return Mapped.Item(myControl)
        Else
            Return ""
        End If
    End Function

    ''' <summary>
    ''' Set function used by the ProvideProperty attribute
    ''' </summary>
    ''' <param name="myControl"></param>
    ''' <param name="value"></param>
    ''' <remarks></remarks>
    Public Sub SetPropertyName(ByVal myControl As Control, ByVal value As String)
        'Add property/control pair to dictionary
        If Mapped.ContainsKey(myControl) Then
            Mapped.Item(myControl) = value
        Else
            Mapped.Add(myControl, value)
        End If
        'Add event handler for control type
        If myControl.GetType() Is GetType(TextBox) Then
            Dim tb As TextBox = myControl
            AddHandler tb.TextChanged, AddressOf Me.TextChanged
        End If
    End Sub

    ''' <summary>
    ''' The IExtenderProvider interface, returns true if the passed control type can be extended.
    ''' </summary>
    ''' <param name="extendee"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CanExtend(ByVal extendee As Object) As Boolean Implements System.ComponentModel.IExtenderProvider.CanExtend
        If extendee.GetType Is GetType(TextBox) Then
            Return True
        Else
            Return False
        End If
    End Function

    ''' <summary>
    ''' Used to set the class the form will be updating
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property FormObject As Object

    ''' <summary>
    ''' Internal flag the the form is being filled
    ''' value changes should be ignored when true
    ''' </summary>
    ''' <remarks></remarks>
    Dim Filling As Boolean = False

    ''' <summary>
    ''' Called to initiallize all controls from the values stored in the class
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub FillFromClass()
        'Check for null
        If FormObject IsNot Nothing Then
            Try
                'Set filing flag, use try...finally structure to
                'ensure the flag is always turned off
                Filling = True
                'Loop through all handled controls
                For Each item In Mapped
                    'Get control on property name from dictionary item
                    Dim Cntl As Control = item.Key
                    Dim PropertyName As String = item.Value
                    'Get value from class
                    Dim Value As Object
                    'Get reflection property
                    Dim Prop = FormObject.GetType().GetProperty(PropertyName)
                    'Check null
                    If Prop IsNot Nothing Then
                        'get property value
                        Value = Prop.GetValue(FormObject, Nothing)
                        'Set value according to control type
                        If Cntl.GetType() Is GetType(TextBox) Then
                            'Set text property for text boxes
                            Dim TB As TextBox = Cntl
                            TB.Text = Value
                            'Done!
                        End If
                    End If
                Next
            Finally
                Filling = False
            End Try
        End If
    End Sub

    Private Sub TextChanged(ByVal sender As Control, ByVal e As EventArgs)
        'Check for DesingMode
        If Not DesignMode Then
            'Check if the control is being filled
            If Not Filling Then
                'Check for null
                If FormObject IsNot Nothing Then
                    'Get the name of the property bound to control
                    Dim PropetyName = GetPropertyName(sender)
                    'Check if found
                    If PropetyName <> "" Then
                        'Get property using reflection
                        Dim Prop = FormObject.GetType().GetProperty(PropetyName)
                        'Check null
                        If Prop IsNot Nothing Then
                            'Get value based on control type
                            Dim Value As Object
                            If sender.GetType() Is GetType(TextBox) Then
                                'Get text property
                                Value = CType(sender, TextBox).Text
                            Else
                                'Unsupported control type
                                Return
                            End If
                            'Set the value of the class to the new value
                            Prop.SetValue(FormObject, Value, Nothing)
                            'All done!
                        End If
                    End If
                End If
            End If
        End If
    End Sub

End Class

Now, if you build you project, you should be able to drag and drop the provider control right onto your form.

Let's create a simple class to test our new control.

Public Class ExampleClass

    Public Property Name As String

    Public Property City As String

    Public Property State As String

    Public Sub New()
        Name = "Testing Testerton"
        City = "Anytown"
        State = "WI"
    End Sub

End Class

Simple enough. We also need a form with some text boxes, like this.

After you drag a ControlMapper onto your form, you will notice that it appear in the designer in the component tray. You will also see that each text box will gain a new property.

Now for each of the text boxes, you just have to fill in the new PropertyName property with the name of the property in ExampleClass you want it to be mapped to. In the example form, we will create a new instance of ExampleClass and assign the ControlMapper1.FormObject that instance.

        FormObject = New ExampleClass
        ControlMapper1.FormObject = FormObject

Then to demonstrate that the form filling works, we will call ControlMapper1.FillFromClass() in the Load event of the form.

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Fill the form with the class values
        ControlMapper1.FillFromClass()
    End Sub

Lastly, we can demonstrate that the updating works by displaying a message box with the updated values when we click on the button.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Msg As String = String.Format("Name: {0}, City: {1}, State: {2}", FormObject.Name, FormObject.City, FormObject.State)
        MsgBox(Msg)
    End Sub

Here's the complete example form code.

Public Class Form1

    Dim FormObject As ExampleClass

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.

        'Setup form object, and add to control mapper
        FormObject = New ExampleClass
        ControlMapper1.FormObject = FormObject
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Msg As String = String.Format("Name: {0}, City: {1}, State: {2}", FormObject.Name, FormObject.City, FormObject.State)
        MsgBox(Msg)
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'Fill the form with the class values
        ControlMapper1.FillFromClass()
    End Sub
End Class

Lets see this in action. First the form fill.

The let's edit the values.

Let's click the button to see if the class was updated.

It may seem a bit much for a filling a couple text boxes, but when multiple control types are supported, the forms get big, and there are lots of forms, such an automation of the fill-form/update-object cycle can be a big time saver when building your forms. It reduces coding needed to make the form and update the form, and by implementing a reusable component, reduces the risk of introducing errors when you update.

Download the Sample Project.


Posted in VB.Net | Tagged , , , | Leave a comment

Create an Enum ComboBox in VB.Net

There are many things to consider when you write code. Often times you are focused on what you are trying to deliver to your customer. Lately, I’ve been trying to focus more on what will make my job as a programmer easier. Mostly that boils down to two things I like in my code, re-usability and ease of updating. In the past I’ve found myself writing the same code over and over again, and when it came time for changes, updating the same code in a bunch of different places.

Consider this, you have a reasonably large number of forms/controls in your application and many of them contain a drop-down list of the same set of values. Usually, you might just edit each combo box and type in the values for each instance of the list on each form/control it appears on. However, if you need to update those values, you now have to do it in many places and you may forget one and thus introduce a bug into your program. One solution is to create a drop-down list that automatically loads its values from an enumeration. That way every instance of this list will always be the same and can be added by just dropping it onto the form/control without having to set its properties.

To do this, you need to first create a new class that inherits from ComboBox and accepts a type parameter T. This will be your generic base class that will do all the work.

Public Class EnumComboBox(Of T)
    Inherits ComboBox
End Class

Since you are inheriting from ComboBox, your new control has most of the functionality it needs already. Next, it’s just a matter of using reflection over the enumeration type passed in the type parameter T to fill in the DataSource property. You can do this in the constructor, and it looks like this:

    Public Sub New()
        MyBase.New()
        'Drop down list style, no text entry
        Me.DropDownStyle = ComboBoxStyle.DropDownList
        'Get type variable
        Dim EnumType As Type = GetType(T)
        'Check if it really is a enum
        If Not EnumType.IsEnum Then
            Throw New Exception(String.Format("Type {0} is not an enumeration.", EnumType.Name))
        End If
        'Get enum values
        Dim Values() As T = [Enum].GetValues(EnumType)
        'Setup datasource
        'Use linq query
        Dim NewItems = From x In Values Select Key = [Enum].GetName(EnumType, x), Value = x
        'Set datasource to NewItems
        DataSource = NewItems.ToList
        'set display and value members
        DisplayMember = "Key"
        ValueMember = "Value"
    End Sub

First we are setting the DropDownStyle property to DropDownList, as this disables the free-entry text box portion of the ComboBox. The next statement, Dim EnumType As Type = GetType(T), retrieve a type variable that contains the reflection information we need. We also added a check to the IsEnum property just to make sure that the type parameter is actually and enumeration type. The line, Dim Values() As T = [Enum].GetValues(EnumType), is pretty simple and just retrieves an array of all the values in the enumeration. Next, we are using a LINQ statement to pair up each value with its name into an IEnumerable of a generic type. Note that we gave the properties in the generic type the specific names Key and Value. Then we set the Datasource property to be NewItems.ToList. Setting the Datasource directly to the LINQ query object doesn’t work, as the ComboBox class doesn’t seem to recognize query objects as a valid data source. ToList processes the query and converts it into a list object. Lastly, we just set the DisplayMember and ValueMember properties to “Key” and “Value”.

There are two other additions to this control. One is simply a property that exposes SelectedValue as type T rather that just plain object. This mostly just helps when coding against the control.

    Public ReadOnly Property EnumValue As T
        Get
            Return SelectedValue
        End Get
    End Property

The other addtion is just a hack to work around some problems with the forms designer. Basically what happens is the designer tries to serialize properties from the controls when you place them on a form/control. Well, if you try to serialize our datasource property, it will fail since it can’t serialize an anonymous type. That error will prevent you from adding your control to a form/control.

    <System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)>
    Shadows Property DataSource
        Get
            Return MyBase.DataSource
        End Get
        Set(ByVal value)
            MyBase.DataSource = value
        End Set
    End Property

That leaves us with the complete control code, shown here.

Public Class EnumComboBox(Of T)
    Inherits ComboBox

    Public Sub New()
        MyBase.New()
        'Drop down list style, no text entry
        Me.DropDownStyle = ComboBoxStyle.DropDownList
        'Get type variable
        Dim EnumType As Type = GetType(T)
        'Check if it really is a enum
        If Not EnumType.IsEnum Then
            Throw New Exception(String.Format("Type {0} is not an enumeration.", EnumType.Name))
        End If
        'Get enum values
        Dim Values() As T = [Enum].GetValues(EnumType)
        'Setup datasource
        'Use linq query
        Dim NewItems = From x In Values Select Key = [Enum].GetName(EnumType, x), Value = x
        'Set datasource to NewItems
        DataSource = NewItems.ToList
        'set display and value members
        DisplayMember = "Key"
        ValueMember = "Value"
    End Sub

    <System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)>
    Shadows Property DataSource
        Get
            Return MyBase.DataSource
        End Get
        Set(ByVal value)
            MyBase.DataSource = value
        End Set
    End Property

    Public ReadOnly Property EnumValue As T
        Get
            Return SelectedValue
        End Get
    End Property
End Class

Now, another issue with the Visual Studio form designer, is that you cannot add a generically defined control through the control toolbox. To get it to work in the designer you just have to create a non-generic class, like this.

Public Class ComboBoxExample
    Inherits EnumComboBox(Of ExampleEnum)

End Class

At this point, if you build your project, ComboBoxExample should appear in your toolbox to be dropped onto your control.

That’s it. You now have a reusable drop down list, based on an enumeration that, no matter where it’s used will always reflect the correct values.


Posted in VB.Net | Tagged , , , | 1 Comment

Flexible way to save Android Activity State

Today I would like to introduce a flexible and easy method for saving and restoring your Activity state in your Android App. Typically in Android, and Activity can be destroyed by the system for various reasons, either to save memory while the Activity is not visible, or to rebuild the layout when device orientation changes. Whatever the case, it’s your responsibility to save any variables when the Activity goes away and restore them when it comes back. This is accomplished by overriding the onSaveInstanceState and onRestoreInstanceState methods of the Activity object. This is explained in more detail here.

Now, what is usually suggested is to set and read info using the various get and put methods of the Bundle object that is passed to the methods in order to save and restore state. Kinda like this:

		public static final String SAVE_KEY1 = "SAVE_KEY1";
		public static final String SAVE_KEY2 = "SAVE_KEY2";
		public static final String SAVE_KEY3 = "SAVE_KEY3";

		@Override
		protected void onSaveInstanceState(Bundle outState)
		{
			outState.putString(SAVE_KEY1, stringValue);
			outState.putInt(SAVE_KEY2, intValue);
			outState.putFloat(SAVE_KEY3, floatValue);
		}

		@Override
		protected void onRestoreInstanceState(Bundle savedState)
		{
			stringValue = savedState.getString(SAVE_KEY1);
			intValue = savedState.getString(SAVE_KEY2);
			floatValue = savedState.getString(SAVE_KEY3);
		}

Ok, so you’re thinking, what’s the big deal about that? It seems pretty easy. Well, it is pretty easy, and for most situations its good enough. However there are a couple things I don’t like about the approach. First, if you have a large number of fields to save and restore, this can seem tedious. Also, if your data is not flat (i.e., a hierarchy of complex data structures), this simple method might not get the job done. Second, its just a code maintenance issue. Every time you change the data in your activity, you have to update these two functions and re-test them. You run the risk of introducing bugs, like loading the wrong saved value into the wrong field.

The solution to these potential complications is simple. Place all your data for your Activity in a class, and then serialize and deserialize that class as a whole. That way, your onSaveInstanceState and onRestoreInstanceState implementations will be the same no matter the size or complexity of your state information, and if the information changes, you will not have to alter these methods. The only thing you need to do is ensure that your class in which you will save your Activity state is able to be serialized. This is done by marking it with the Serializable interface. As long the class is marked and any types within the class are serializable, you are good to go. However, if you do have some object that just can’t be serialized, you may declare it as transient. This prevents it from being serialized with all the other fields. Here is a short example of a serializable class:

		public class State implements Serializable
		{
			public enum ExampleEnum implements Serializable
			{
				PAUSED,
				RUNNING,
				OVER
			}
			//The Transient keyword excludes the field from serialization
			public transient NonSerializableClass nsc;
			public int anIntegerValue;
			public int anotherIntegerValue;
			public ExampleEnum exampleEnum;

			public LinkedList listOfStrings;
			public LinkedList listOfInts;
			public LinkedList listOfFloats;

		}

This example just contains some simple values, a couple lists of simple values, and an enumeration. Note that the enumeration is also marked as Serializable.

Ok, so the we have a serializable class that holds all the info we need. Now what? Well to actually perform the serialization, we can use the ObjectOutputStream class with the help of the ByteArrayOutputStream class to turn our class into a array of bytes that we can place in the Bundle. ObjectOutputStream does the work of serializing the object to the ByteArrayOutputStream, where the array of bytes is retrieved.  Then, to do the opposite, we use the ObjectInputStream and ByteArrayInputStream class to turn an array of bytes back into an object. Here is the code for that:

		public static final String SAVE_KEY = "SAVE_KEY";

		public State state;

		@Override
		protected void onSaveInstanceState(Bundle outState) throws IOException
		{
            //Serialize state object and write it to bundle
        	ByteArrayOutputStream bos = new ByteArrayOutputStream();
        	ObjectOutput out = new ObjectOutputStream(bos);
        	out.writeObject(state);
        	out.flush();
        	out.close();
        	outState.putByteArray(SAVE_KEY, bos.toByteArray());

        }

		@Override
		protected void onRestoreInstanceState(Bundle savedState) throws StreamCorruptedException, IOException, ClassNotFoundException
		{
			if(savedState != null)
			{
				if(savedState.containsKey(SAVE_KEY))
				{
					ObjectInputStream objectIn = new ObjectInputStream(new ByteArrayInputStream(savedState.getByteArray(SAVE_KEY)));
					Object obj = objectIn.readObject();
					State = (State) obj;
				}else
				{
					state = new State();
				}
			}
			else
			{
				state = new State();
			}
   		}

And thats that. Note that this code was pulled from a working example, but as always issues can be introduced in the simplification and presentation process. If you find a problem, let us know in the comments!


Posted in Android, Java | Tagged , , , , | Leave a comment