I am just away to start my first Windows Mobile Application. I am going to be using Windows Mobile 5.0 on the device, and Visual Studio 2005, targeting the .Net Compact Framework 2.0, using C#. I am also going to be using SQL Server 2005 Compact Edition.
I am looking for just a few general pointers on Windows Mobile Development.
I have just finished watching a series of videos on MSDN which I found to be very useful, but there were still some unanswered questions.
For instance, part of me wants to create separate layers for Data Access and Business logic, because that is what I would do in a web app, or a windows form app, but is that the approach to take on Windows Mobile. What are the overheads involved in using this approach.
Is it better to compile all helper methods code down to a DLL, and reference that in my project?
As I said, this is going to be my first Application, and would prefer to start off in the correct way, so any pointers would be greatly appreciated!!
There will never be more than one user of the database, so opening and closing connections isn't as big a deal. You can open the connection right off, and leave it open. I guess I have done a DAL, business objects, and UI kind of an interface, but they certainly weren't distributed.
Another point that is pretty important, in my opinion, is to use only one form. Searching around this forum, you will see me and others expand on this point, but the key is that loading a form takes measurable time. A far better approach is to use panels and swap them in and out of the visible area. This is effectively instantaneous, but it makes organization a bit more important.
I see what you are saying about there only being one user, I think part of me is still thinking in the web world, need to get my head out of that for a while. I guess the reason behind me thinking about using a DAL layer with Business Objects, is that I guess there is the possibility that there way the data is getting to the database on the device. At the minute, it is going to be done using web methods exposed on the back end server when the PDA is docked, so part of me thought I might adopt a provider model so that it could be a simple configuration change to change the back end. And my concern was that this would add too much additional overhead on the PDA.
One form!?!?! Now that is a very interesting concept!!! All the tutorials etc that I have seen have never mentioned this approach! Would you happen to have a simple sample application where this approach is adopted?
I'll be darned. I went looking for an example with the panels on here, and found nothing. I mention it many times, but I never posted any code. It may be that there is so little code worth posting. In fact, there may be NO code worth posting, but here's what I do (with a little code):
1) Add one big form, as big as possible.
2) Add a panel sized to the size of the PDA screen (240x268 on my Toshiba)
3) Color the panel. I do this just so that every panel has a different color for ease of finding them, not for any other reason.
4) Add a single integer variable to the form called something like theState, because the form is just a big state machine.
5) Add a sub that looks like this:
vb Code:
'Call this to show a specific panel chosen by theState variable.
Public Sub ShowPanel()
'First clear what is there.
ClearScreen()
Select Case theState
Case 0
SetUpSessionPanel()
Me.pSession.Top = 0
Case 1
SetUpShowDBPanel()
Me.pDatabase.Top = 0
Case 2
ClearVariables()
SetUpSwitchPanel()
Me.pSwitch.Top = 0
Case 3
Me.pConnection.Top = 0
Case 4
SetUpForEffortView()
Me.pView.Top = 0
Case 5
SetUpForFishView()
Me.pView.Top = 0
Case 6
SetUpForGender()
Me.pGender.Top = 0
Case 7
SetUpFinalFish()
Me.pFinalFish.Top = 0
Case 8
SetUpGroupFinal()
Me.pFinalEffort.Top = 0
Case 9
SetUpForMarks()
Me.pTagsAndMarks.Top = 0
Case 10 To 20
SetUpNumberPad()
Me.pNumPad.Top = 0
Case 21 To 23
SetUpForDate()
Me.pDatePick.Top = 0
Case 25
SetUpComments()
Me.pComPanel.Top = 0
Case 26
SetUpCatchPanel()
Me.pDailySummary.Top = 0
Case 27
SetUpLengthCrit()
Me.pLengthCrit.Top = 0
Case 100
SetUpSessionPanel()
Me.pSession.Top = 0
Case 101
SetUpGroupFinal()
Me.pFinalEffort.Top = 0
Case 106
SetUpForGender()
Me.pGender.Top = 0
Case 107
SetUpFinalFish()
Me.pFinalFish.Top = 0
Case 109
SetUpForMarks()
Me.pTagsAndMarks.Top = 0
Case 110 To 121
SetUpNumberPad()
Me.pNumPad.Top = 0
End Select
End Sub
As you can see, the theState variable selects which panel will be shown. In this case, I added a sub for each panel to set it up. This gets called just before the panel gets swapped into the view pane, so it acts like the Load Event for a form.
6) The ClearScreen sub looks like this:
vb Code:
'Use this sub to clear off all the panels.
Private Sub ClearScreen()
Me.pSession.Top = 300
Me.pSwitch.Top = 300
Me.pNumPad.Top = 300
Me.pFinalFish.Top = 300
Me.pFinalEffort.Top = 300
Me.pGender.Top = 300
Me.pDatabase.Top = 300
Me.pTagsAndMarks.Top = 300
Me.pConnection.Top = 300
Me.pView.Top = 300
Me.pDatePick.Top = 300
Me.pComPanel.Top = 300
Me.pDailySummary.Top = 300
Me.pLengthCrit.Top = 300
End Sub
Basically, the Panel.Left property stays at 0 for all panels, so the ClearScreen has the result of moving all panels off the visible area, then the ShowPanel select statement shifts just the right one up into the visible area. Of course, all except one are already off the view area, but it is easier to re-set the Top property to 300 for all panels rather than keep track of which one needs to be switched. The branching needed to figure out which panel is currently visible is more expensive than just setting the property for all of them.
7) Each panel is now responsible for two things: A) Validating and storing it's state into whatever variables apply, and B) Setting the theState variable for the next form that should be displayed.
Anything like a menu item would also just need to set theState and call ShowForm. The rest is handled. Thus all panel swapping is just the two steps of setting the variable and calling the sub. In at least one program, I passed the theState variable to the ShowForm sub as an argument, but I found that I really needed to retain theState as visible for all to see. The reason for this can best be seen by looking at Case 10-20. For all of those cases, the exact same panel is being swapped in. That panel is nothing but a ten digit number pad with decimal and All Clear buttons, along with a textbox and a label. It's the same form, but the value in the label, whether or not the decimal button is visible, and the validation of the textbox is different depending on what theState actually is. Therefore, the panel selects the validation based on theState, so the variable needs to be visible.
As for the multi-tier: After a bit of thought, I realize that I have ALWAYS used at least a DAL layer for portable projects that used a database, and generally I used a Business Object layer, though perhaps a lighter one than might suit a desktop app.
One further point that I learned the painful way, but which may not apply to you is that memory on PDA's can be terribly volatile. Therefore, I always save my databases to an SD card rather than in system memory. That way, when my system battery runs down, I lose the program, but I don't lose the data. Even if the PDA goes swimming, I don't lose the data. There's a thread on here somewhere about my testing an SD card by running it through various home appliances. The dishwasher and washing machine caused no problems, but boiling the card in salt water for five minutes destroyed it utterly.
You have so little real estate on the form that you start thinking about tricks that will fit the mobile-concept of click-with-the-pin.
For instance one of our app's let's the user select a kid by Lastname, First, middle or nickname.
So a label on the form holds "Last Name" with a textbox to the right. Click the LABEL itself and "Last Name" becomes "First Name" - prompt changes on click.
Big green button to the right of the textbox. Click that and GREEN means GO and what you typed in the textbox is processed. GREEN changes to YELLOW to show the process is running. If an error occurs the button changes to RED. All this done to drive attention to the fact that this button is the control - as low-level as driving a remote control car in your kitchen.
ListView on the lower 80% of the display now shows kids with that "name" - keep in mind for later that we refer to this as the "first" listview...
Click a name and you have selected the kid. We happen to "sort" that kid to the top - but you won't see that until you return.
Now up comes the kids schedule of classes - in front of the schedule we display the picture of the kid. To get rid of the picture you click it - it disappears - schedule of classes was right under it (actually bigger then the image - so it's obvious) in a "second" listview.
Click a class and that "second" listview reloads with the "kids in that class".
Click a kid and that kid is added to the "first" listview - at the top. But we aren't looking at that listview right now - but we did pop that data on the hidden control). Instead we are showing this kids classes in that "second" listview (actually if we found his image on file we displayed it - otherwise we beeped - you don't want to give many message boxes).
Now how to get back to that "first" listview. Well - the name of the kid is in a label right above the visible "second" listview with his classes. Just click that LABEL and you effectively hide the "second" listview and bring up the "first" listview. This kid you just clicked off of is at the top of the list. The kid that started this mess is just below him.
All of this experience intuitive in my opinion.
All of this experience without COMMAND BUTTONS and MENU options.
It is just so different - a real step back to think about UI on a 2x3 inch screen!
We market to schools - PDA's to track where a kid is supposed to be when found skipping classes. PDA's to allow phys ed teachers to count push-up's and curl-up's and other stuff for fitness awards. That GUI was intense - I'll see if I can find a screen shot in another thread.
btw - we use MS SQL CE - it's nice. You can authenticate to a NETWORK SQL SERVER from the PDA - it's an interesting trick. We do this to download and upload data to the central district database.
Last edited by szlamany; May 16th, 2008 at 11:00 AM.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
Thank you both for your posts, they have been very helpful and given me lots to think about!!
szlamany, I have read about the possibility of synchronizing with a backend server and essentially this is what I want to do, however, in my case, the backend server is an Oracle Database, so I don't believe that that option is available. that is where the idea of the web service with exposed web methods came from to do the synching.
Oh, and some screen shots would be very useful!! Thank you very much!!
Shaggy, thanks for posting the code. I think that this is an approach that I will look into very closely. There is due to be a good number of forms in this application that i am working on, so any performance improvements that can be gained will be very useful.
Thanks again, I will post back once I have done some more work on the application, because no doubt I am going to get stuck on something!!
So as you might have got out of my last two threads that we do a lot with a label, textbox and two listviews.
Check out what drives this - a table on the network called APCConfig_T - APCTYpe=1 is the screen shots you see above - APCTYpe=2 is a phys ed teacher app the same program supports. Table gets downloaded to the PDA/PPC when it's sync'd and then controls it's behavior.
APCItem1 being a 1 or 2 tells that "query" to the right which listview to drop into.
Code:
Select CL.Class, CL.Period "Per_40", CL.Days "Days_40", ...Where StuId=@tag Order by...
This query above is from that table - showing the =@tag part - these queries are "homegrown" parameterized and bound to the app. Even APCFlag1 "tells" the app how to "build" error messages that bind to data.
Calling the column Days_40 makes it 40 points wide - all this controlled from a table on the NETWORK that when we change auto-sync's to the PPC's.
*** Read the sticky in the DB forum about how to get your question answered quickly!! ***
Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".
I wrote a program that the Phys Ed teacher might be interested in: It comes up with a random number of exercises, picks that number of exercises from a list, and sets a random number of reps from a list. That would be a good program for a particularly sadistic Phys Ed teacher. I use it for my exercise routines, as it keeps me from getting trained to a particular routine.
x2
I am developing a "Quiz" type app and each question appears on its own form. At present I have 20+ forms. It would be VERY slick to reuse the same form over and over again. Any chance of a sample project with 2 or 3 forms demo'ed? From there I could replicate and attempt to revise my 20+ forms down to 1 ...
Thanks much, Magohn