Sybase Brand Color Bar
  blank
May 26th, 2010 | Tags:

PowerBuilder 12 has been released, and if you’ve been paying attention, you know that it now comes in two flavors!  There’s PB12 “Classic” for traditional Win32, WinForm, WebForm, .NET Assembly, and J2E component targets, and PB12 .NET for WPF (Windows Presentation Foundation) and WCF (Windows Communication Foundation) proxy targets. 

 

One of the overriding goals of this release was to give PB developers an easy migration path that would allow them to bring their tried-and-true Win32 PowerBuilder applications into the new and exciting world of WPF.  While it’s unrealistic to assume that all PB apps, big and small, will migrate cleanly into PB12.NET with zero refactoring, there is one specific class of applications that will absolutely require some coding work to make the transition.  These would be any applications that invoke SOAP-based web services, using the SoapConnection and SoapException extension classes. These have been deprecated in PB12.NET (don’t worry – they still exist in PB12 Classic!).  They have been replaced with the new WCF proxies.  However, the migration process does not automatically convert the existing web service proxy objects/projects into WCF proxy projects.  But don’t worry, I’m here to help…

 

This post is going to walk through the process of migrating the existing Web Services sample app, which was featured in a previous blog post, into a WPF/WCF application. You’ll see that it’s relatively easy, and results in much cleaner and more streamlined coding.

 

Step 1:  Migrate the existing target into PB12.NET

 

This step is very simple.  Open PB12.NET, and create a new Solution (what we used to call a Workspace).  This creates an empty .PBWX file in a folder of your choosing.  Then click Add Target…  This prompts you for the location of the an existing .PBTX (WPF) or .PBT (Classic) target file.  If you installed the Sample Applications during the PB12 install, the target you want should be found in the folder C:\Documents and Settings\All Users\Documents\Sybase\PowerBuilder 12.0\Code Examples\Web Services.

 

Select the WS.PBT file.  This target has NOT been migrated to PB12.NET, so the Migration Wizard will kick in.

 

PB12.Net Migration Wizard

 

Note that this is a non-destructive migration, unlike previous versions of PB.  You’re asked for two locations – and the terminology used can be a little confusing.  The first location, labelled “Target”, is actually the location of the existing Source – i.e., the code you’re migrating FROM.  The second, labelled “New location and target file” is both the folder location into which PB will place the migrated code AND the new target name.  The PBLs referenced in the “target” are not changed at all – the migrated code is placed into the “new” directory – PBL for PBL. 

 

Walk through the remaining panels of the wizard, accepting the defaults, and you’ll get to the main PB12.NET IDE.

 

Step 2: Generate the WCF Proxies for the services

 

The old SOAP proxies are useless in PB12.NET.  In fact, once we finish replacing the existing proxies with WCF proxies, you can even remove the Proxies.PBL from the target library list.  None of the proxy or structure classes in that PBL will be referenced.

  • Select File >> New >> PB Library to create a new PBL that will store the new WCF Proxy classes.  I’m calling mine WCFProxies.PBL.
  • Select File >> New >> WCF Client Proxy to start the Proxy wizard.  You’ll have to do this for each of the old SOAP web service proxies, but let’s start with the Movie Times service.
    • I’ll name this project p_movietimes_wcfclient, and place it in the WCFProxies PBL.
    • The service URL is:
      http://www.ignyte.com/webservices/ignyte.whatsshowing.webservice/moviefunctions.asmx?wsdl
    • Leave the NameSpace entry blank.  Name the proxy assembly movietimes.dll, and place the proxy class into WCFProxies.PBL.
    • The next panel shows the list of services (there’s only one), and the data structures (there are several).  Click Next, then Finish.  This opens the Project Painter and loads p_movietimes_wcfclient
    • Now click the Generate Proxy button to create the proxy object class.
  • Do this for each of the web services that currently have proxies.  I’ve gone ahead and completed this process and stored the zipped solution files here.  Note:  some of the web services are no longer active, so the code in the cb_invoke button of their corresponding visual user objects has been commented out.

 What comes out:  you’ll get WCF proxy objects in the WCFProxies.PBL.  These are real PowerScript objects, with methods and events that you can open and inspect.  You’ll also (optionally) get new additions into the References folder, for any structure classes that are called out in the WSDL.  So, in your PowerScript, you’ll declare the proxy with the class type that appears in the PBL, and any structure references that appear will come from the References folder.

 

Step 3: Remove the deprecated SOAP client classes

 

The SoapConnection, SoapException, and SoapPBCookie classes are obsolete in PB12.NET.  All of the processing that these classes used to perform has been incorporated directly into the WCF proxy class (which we generated in Step 2).  All we need to do is delete these from the WS PBL, and then remove any references to them from the PowerScript code.

uo_ancestor (tabpages.pbl)

  • Remove the instance variable declaration for the SoapConnection class.
  • Remove all the code from the Constructor and Destructor events.
  • Remove both of the InstantiateService() methods. Select the method, then choose Edit >> Delete Function…

  

Step 4: Call the new WCF proxy classes

 

The uo_ancestor class used to manage all the SOAP client and proxy instantiation.  Since none of that is necessary anymore, all we need to do is open every descendent of uo_ancestor, and fix the code in their cb_invoke::clicked event to instantiate and invoke the new WCF proxies.  Again, let’s start with uo_movietimes.

uo_movietimes (tabpages.pbl)

cb_invoke::clicked

  • Replace the local declarations and remove the call to InstantiateService()
    • s03_movieinformation on line 1 becomes movietimes_MovieInformationSoapClient  (Intellisense really helps here).
    • s03_theatre on line 2 becomes movietimes.Theatre
    • Comment out the entire IF statement that calls InstantiateService() on line 13.  Replace it with:
      px_Service = CREATE movietimes_MovieInformationSoapClient
    • Comment out the final END IF on the last line.
  • Fix a type casting exception that will be thrown at runtime (the C# compiler is much more strict than the PowerScript compiler!)
    • The local ANY variable response needs to be changed to an array declaration, since the proxy’s GetTheatresAndMovies() method returns an array of movietimes.Theatre structures.  PowerScript allows an Any to hold literally any reference, but C# has strict rules about array to non-array assignments.

That’s really all the code that needs to change!   I did go ahead and comment out the code that invokes the dead web services, since I couldn’t generate new proxies for them.  And I changed the MovieTimes user object layout so that the Canvas element was nested inside a Grid with two RowDefinition.  This makes the Resize logic completely unnecessary, as WPF handles resizing anything inside a Grid cell.   But that’s the topic of the next blog post – no reading ahead…  ;)

The final step would be to perform a full Build, and a Deploy, then test out the Movie Times web service call. 

 

Download the sample PB12.NET solution by clicking here

 

Enjoy!

-Paul-

May 1st, 2010 | Tags: , , , ,

Actually, it’s here!  Generally available for licensed users at the Sybase Product Download Center!

Rocking .NET!

The long-anticipated update to PowerBuilder is the 16th major release in 19 years, and that doesn’t count the dozens of maintenance releases and HUNDREDS of EBF patches.  But this one is special…  The last really substantial overhaul of the IDE came with the release of version 8.0, which introduced the System Tree, Workspaces and Targets, and tighter SCC integration.

The first thing you’ll notice when you install PB12 is that it actually contains TWO separate IDEs.  PB12 “Classic” is essentially the same interface that we’ve known since version 8.0, and continues the tradition of allowing you to build Win32 client applications, .NET Winform and Webform apps, .NET Web Services and Assemblies, and JEE components for EAServer, JBoss, WebLogic, or Websphere.  All of these are distinct “target” types and can be edited from a single Workspace in PB12.

PB12.NET is a second IDE that will contain two target types: WPF (Windows Presentation Foundation) applications and WCF (Windows Communication Foundation) client proxies.  WPF is the new graphical rendering engine for Windows, and it replaces the aging Win32 GDI architecture.  The language for designing the user interface layer of a WPF applications is called XAML (EXtensible Application Markup Language), which is an XML-based syntax.  The good news is, PB12.NET actually generates the XAML for you interactively from the grapical design pane!  (But it’s still a good idea to get familiar with the XAML syntax…)

PB12.NET leverages the Microsoft Visual Studio Isolated Shell, so it’s going to look a little different to veteran PB developers.  It will look and feel like Visual Studio, but with the familiar PowerBuilder coding experience that we’ve all grown familiar with.  You still write event and function scripts in PowerScript, and develop Datawindows, and your existing apps should migrate to WPF targets with little or no refactoring required.

It’s important to note that this is NOT a Visual Studio plugin – and there’s a big distinction.  If PB12.NET had been constructed as a VS2008 plugin, you would have to purchase and install Visual Studio 2008 to run PowerBuilder!  This is why we went in the direction of the Isolated Shell.  Everything you need comes in the PB12 install – you do NOT need to install Visual Studio or Expression Blend to construct fully functional WPF applications.

Here’s a link to the Trial Download of PB12.  Note that the GA version had an issue with our licensing software, which resulted in valid license files being rejected on machines that had participated in the Beta program at any time.  This issue has been fixed, and the EBF release for that specific defect can be found at this link.

Enjoy!

-Paul-

April 26th, 2010 | Tags: , ,

This really isn’t a Sybase-related post.  This is about my first real exposure to the power of Social Media and Social Networking.

I mean, I’ve seen the Youtube clip of the flashmob that The Black-Eyed Peas organized for Oprah’s kickoff show.  That was all organized through Twitter, and the event quickly evolved from a handful of artists to include well over 21,000 people.   But last night really was the first time I was personally affected by this phenomenon, and I thought it important enough to blog about.  It’s a real lesson in the way companies today are actively monitoring sources like Twitter and Yelp to continuously improve their customers’ experiences, and to protect and enhance their brand.

I’m down in Orlando for the RIM WES2010 Conference, representing Sybase and the Unwired Enterprise.  I’m staying at the conference hotel, the Marriott World Center. It’s a gorgeous hotel, with a first-class spa and golf course.  The room I was given was… less than desirable.

Here’s a photo of the view I had:

Nice view of the lobby roof!

Nice view of the lobby roof!

Now, it’s a Marriott, so the room was perfectly nice, and clearly up to the usual Marriott standards of excellence.   And I’m absolutely NOT a complainer – you know the type…  But I’d been looking forward to this trip, and being assigned this room was kind of a downer.  So I logged onto Twitter and posted the following at about 11pm:

“At the Orlando Marriott World Center for RIM WES 2010. But I have the crappiest room in the hotel. Posting photos of the view in the AM.”

I then went to bed.  I awoke to find the following letter slipped under my door sometime during the night:

Dear Mr. Horan,

Thank you for your continued loyalty as a Marriott Rewards member!  Please accept my sincerest apologies for your current room situation on the 4th floor of the East Tower.  Unfortunately, due to the large volume of check-ins, I did not have a room for you to move into tonight.  I have setup a King Poolview…for you to move into on Monday, if you desire.

Warm regards,

Zachary Long, Assistant Front Office Manager
Orlando World Center Marriott

Sure enough, I’ve been upgraded to a sweet room overlooking the pool on the 8th floor.  And here’s the upgraded view:

Poolview

Poolview

Now, I have no proof that this upgrade was a direct result of my tweet.  But I don’t think it matters – Marriott did the right thing by me, no matter what the catalyst was.

I think the lesson is clear.  Companies that are serious about protecting and enhancing their Brand are listening to Social Media outlets to hear what people really think about them…

Are you?

-Paul-

January 4th, 2010 | Tags: , , , ,

I hear this question ALL the time…  And frankly, I think the question itself is a little misinformed!  (Of course, I don’t say that to the person’s face…)

The first step is to find out what they’re really asking…

“Do you mean, you want your PB application to run inside a browser, so you no longer have to worry about client-side deployment?”
(And yes, there are still people that think “.NET” means “runs in a browser”…)
If the answer is YES, we talk about the native WebForms capability of PB11.5.  You simply create a Webform target and project object, click DEPLOY, and your existing PB app runs inside an Internet Explorer browser with IIS as the web server.  Alternatively, there’s the Appeon for PowerBuilder utility, which supports additional browser clients and application servers.

If the answer is NO, then the next question is, “Are you saying, you want your PB application to run as a Microsoft Windows Forms app, so you can access the .NET framework classes directly, or use the Smart Client deployment features?”
If the answer is YES, I show them how PB 11.5 apps can be deployed as Winform applications, and how they can reference .NET assembly classes directly from their PowerScript code with conditional compilation blocks.  And with the Smart Client deployment features, even the client-side deployment headaches are taken care of!

If the answer to that question is NO, then I follow up with, “OH!   Do you mean you have PowerBuilder non-visual components that you would like to deploy as .NET assemblies or web services, so that they can be accessed from C# or VB.NET apps?”
If the answer here is YES, then I proceed to demonstrate how easy it is to deploy .NET assemblies or web services right from PB 11.5, with absolutely NO code changes required.  PB 11.5 even supports strong-named assemblies and Code Access Security standards to help ensure code integrity and security.

If I’m STILL getting a blank stare, then I have to ask, “I think I get it…  You want to use Visual Studio as your IDE, and write code in C# or VB - but you’d rather not lose the functionality of the Datawindow…”
This is when I drop Datawindow.NET on them, but I have to explain that we’re now crossing the border from “migration land” into “rewrite land”.  The datawindows that they’ve developed in their existing applications can be reused, and they’re a critical component of the presentation layer.  It’s the business logic layer will need to be completely refactored into the new target language, and there’s no way around calling that a “rewrite”.

If they’re still not satisfied with my answer at this point, then it’s pretty clear what they’re after…  A magic tool that will translate their PB applications into XAML, so they can take advantage of the new Windows Presentation Foundation (WPF) graphical rendering engine, and have their apps run as 100% managed code!  This is certainly an important requirement, as WPF is the future of Windows user interface development and many IT departments are requiring full .NET compliance.
Well, there’s good news and bad news.  The good news is, Sybase is developing a tool that can do this!  The bad news is, it won’t be released for another few months, but the Beta program is still open and you can try it out today!

The bottom line is, you don’t need to “migrate” away from PowerBuilder to embrace .NET in your organization.  PowerBuilder *IS* .NET!

Enjoy!
-Paul-

November 2nd, 2009 | Tags: , , , ,

Back in January, I showed how easy it was to consume SOAP-based web services with PowerBuilder 11.5.  PowerBuilder supports the .NET web services engine, which allows PB apps to invoke very complex web services with very little of the detailed coding required for a similar C# or VB.Net application. The Web Services Proxy wizard parses the WSDL for the service, and automatically creates a proxy object and all the necessary structures and parameter definitions that represent the service’s operations and request/response structures.  Once those are created, the code required to invoke a service and parse the resulting data is extremely simple.

This posting will look at the other side of the equation – using PowerBuilder to create and publish a .NET web service to an Internet Information Services (IIS) instance. We’ll also see just how easy it is to test and debug that service with the PB integrated debugger.

Taking it up a notch

Most of the web service examples I’ve seen have been really limited in functionality, and I’m sure you’ve seen them as well… For example, pass in a ticker symbol and get the current stock quote. Pass in a zip code and get the current time and temperature. YAWN!!!  While those are good at teaching the basics of the SOAP plumbing, most “real world” web services are rarely that simple, and usually require a much more complex XML schema in the request or response message.

You basically have two options when dealing with very complex XML in a SOAP message:

Marshall the resultset into an XML document within the service, and pass it back as a single long string.

This forces the recipient to parse the response using MSXML, or the System.XML classes to extract the data they need. What you end up with is a web service with absolutely no “metadata” in the WSDL that can help the consumer understand the content.

Create a set of strongly-typed structures that accurately represent the data being returned.

This allows the .NET web services engine to create meaningful WSDL for the SOAP-based service.  With this approach, the WSDL contains actual metadata about the request and/or response structure, and the consumer can better understand the nature of the data being returned.

This example will use the second approach, and return a complex, nested hierarchical resultset from a PowerBuilder .NET web service.  We’ll use the “EAS Demo DB 115″ database that ships with PowerBuilder 11.5.

Step 1: Create the .NET Web Service target

You can use an existing workspace, or create a new one.  Once you have that, select File > New and select the Target tabpage.  We’re creating a .NET Web Service target from scratch, so select that path through the Wizard.

  1. Create from scratch
  2. Project name, Library location, and Target name:  I selected OrdersByCustID_ws for mine.
  3. Library search path: accept the default.
  4. PowerBuilder object name: This is the NVO that will be created, and I called mine n_ordersByCustID.
  5. Web Service virtual directory name:  This is the folder location within your local IIS instance where the compiled service objects will be placed.  I selected OrdersByCustID.
    The Web Service URL Preview is an .ASMX page that allows you to test your compiled service.  We’ll use that later.
  6. Resource file and directory list: This is where you’d list image files, 3rd-party .NET DLLs, etc., that your Web Service target will use.  We won’t have any, so just click NEXT.
  7. Win32 Dynamic Library File list:  Again, we won’t be using any, so just click NEXT.
  8. Directly deploy to IIS:  The default server name is “localhost”.
  9. Click FINISH, and you’ve got your target, project object, and nonvisualobject class created in your PBL.

Step 2: Design the Web Service

The first thing you ask is, “What question am I being asked, and what will the answer look like?”  For this example, I designed a query that answers a very basic sales question:  Show me the complete order history for a specific  customer between any two dates.”  The inputs to this question are the customer ID, and the desired From and To dates.  The output will be a nested hierarchy that looks sort of like this pseudo-XML structure:

<Customer>
     <Sales_Order>
          <Sales_Order_Line_Item/>
          <Sales_Order_Line_Item/>
    </Sales_Order>
    <Sales_Order>
        <Sales_Order_Line_Item/>
        <Sales_Order_Line_Item/>
    </Sales_Order>
 </Customer>

For a single customer, retrieve some basic customer information (ID, name, city, state, zip). For each sales_order whose Order_Date is between the From and To date, retrieve the Order_ID, and the Order_Line_Items.   Here’s a picture of the datawindow painter SQL source for that query:

Sales report query

Now, I could take this “hierarchical”-style query, construct grouping levels in the datawindow and use the native XML properties of the datawindow to persist an XML representation of the resultset.  But that would give me Option 1 above, a single string containing the XML data without metadata in the WSDL, and I don’t want that!  What I’m going to do is create three Structure classes that represent the three “levels” of this query, Customer, Order and Order_Line_Item.

The Customer structure will have an attribute which is an array of Order structures, and the Order structure will have an attribute which is an array of Order_Line_Items.  The public method in the nonvisualobject will take three input parameters (custID, fromDate, and toDate), and its return value will be the outer Customer structure.

Here’s a picture of the three Structure classes I’ve created.  You can clearly see how I’ve nested an array of s_order_line_item within the s_sales_order structure, and an array of s_sales_order within s_orders_by_custid.

Result set structures

Step 3: Create the public method within the NVO

This will be the Operation that gets exposed in your WSDL, so choose a name for the method and its arguments that will give the consumer some indication of their meanings.  I chose:

getOrdersByCustID( long al_custID, date ad_from, date ad_to) returns s_orders_by_custid

The code in that method is really pretty simple.  I won’t recreate it here, but you can download the entire example here and review the code yourself.  It basically just instantiates a datastore, retrieves the data, and moves the data row by row, column by column into a local variable that matches the output structure.  The NVO also needs to connect and disconnect from the database, and I placed the code for this in the Constructor and Destructor events, respectively.

Remember that ANY public method or instance variable will be available to be exposed through the web service.  If you create additional methods within the NVO (and my example has both an of_connect() and an of_disconnect() method), then these should be scoped as PRIVATE.  The same goes for Instance variables.  Make them Private, and if you want to expose them, create public Get/Set methods for them.

Step 4: Complete the Project Object and Deploy the Web Service

The most important section of the Web Service Project object is on the Objects tab.  This is where you select the NVO and the methods in that NVO that will be exposed as part of the Web Service.  In the future, you may have web service targets with multiple PBLs, containing multiple NVOs, but this example has one of each.  In the Custom Class Objects treeview, select the n_ordersbycustid object.  Then select the checkbox next to the getOrdersByCustID method in the list of available methods.  Then save the changes to the Project object, and click the Deploy button.  If all goes well, the output window should give you a success message when the service is deployed to IIS.

The Objects tab also allows you to view the WSDL that will be generated for your service (NOTE: some browsers handle this better than others – IE8 seems to work fine, but Google Chrome does not.)  You can also click the Run Web Service button to launch a simple .ASMX page that allows you to test the service.  Let’s do that now!

Step 5: Test the Web Service

Click the Run Web Service button.  This launches the .ASMX page that shows the NVO name, and a link to any exposed methods within the class.  It looks like this:

ASMX Test Page

Click the link to getordersbycustid, and you’ll be prompted to enter values for the input parameters.  You also see the WSDL, presented in the different available W3C versions.  Now, the data in the EAS Demo DB is getting quite old, so you’ll find that order dates are back in the 2003-2006 timeframe.  Use the following values:

  • Customer ID = 101;
  • From Date = ‘2003-01-01′;
  • To Date = ‘2004-12-31′

Then click Invoke to run the service.  If everything works correctly, a new Internet Explorer window will open and present the XML result from the service.  If that doesn’t happen, you can actually run the PowerBuilder debugger and step through the lines of code in the method as it’s running!

Open the debugger and place a breakpoint at some line of code inside the getOrdersByCustID method, say the point where it executes the Retrieve() function.  Then click the “Start Debugger” button.  Now go back to the ASMX page and re-click the Invoke button.  The PB Debugger will stop on your breakpoint, and you can begin step-by-step debugging, examine local, instance, or global variables, set watch variables, etc…

So, PowerBuilder 11.5 can be an integral part of your Service Oriented Architecture, as both a consumer AND a producer of complex SOAP-based web services.   And again, you can download the entire example I’ve just created here.

Enjoy!

-Paul-

October 3rd, 2009 | Tags: , , ,

Here’s a quickie for all you PowerBuilder developers that are currently evaluating the beta of PB.Net (aka PB12). Even though it’s not required to know XAML (because the WYSIWYG layout designer in PB.Net automatically generates it for you), it’s probably a good idea to get familiar with it.  There will be times, as shown in my 3-part series on WPF and XAML development with PB.Net, where you may want to extend the graphical look-and-feel of your application, and you’ll have to do this directly in the XAML code itself.

Well, our good friends at Microsoft have created a little utility that lets you experiment with and validate your XAML code before you bring it over into your PB application.  It’s called XAMLPAD.EXE, and it’s included for free in the .Net 3.5 SDK.  If you have that version of the SDK installed, you can find XAMLPAD.EXE in the folder “C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\”. 

Here’s a screen shot:

XAML Pad application

 

So you can use XAMLPad to do things like develop custom templates and styles outside of PB, before you copy/paste the code into the XAML pane of the PB.Net IDE.

 

Enjoy!

-Paul-

September 28th, 2009 | Tags: , , , ,

If you’ve been following this series, you’ve seen how easy it is (perhaps I should say, “will be”, since PB12 is still in beta…) to use the new features of PowerBuilder.NET. I hope I’ve been able to demystify any uncertainty you’re feeling about the upcoming transition to Windows Presentation Foundation (WPF) and Extensible Application Markup Language (XAML).

In this third (and final?) chapter of the series, we’ll add the final four commandbuttons, flesh out the PowerScipt, then add some custom XAML tags to the presentation layer which will really add some sizzle to the finished Calculator application. The point of this exercise is to show how XAML and WPF allows you to separate the user interface design/implementation from the “business logic” code of a PB.Net application.

 

To refresh everyone’s memory, this series is implementing the sample Calculator application from MSDN, which can be downloaded here. If you’ve gotten this far, we have the basic interface designed, using a GridPanel and some rectangular WPF commandbuttons. Not quite the same look and feel as the MSDN sample, which uses rounded commandbuttons, with cool animations for the MouseOver! and Clicked! events.

Here’s a screen shot of the MSDN sample app in action (which you wouldn’t see unless you have Visual Studio installed):

Sample WPF Calculator from MSDN

 

OK, so that app has some cool extra functionality, like a MultiLineEdit that simulates a running “paper trail” of the calculation history, some extra function keys, and Memory, so a direct “line for line” comparison to our PB.Net version won’t be a decent metric of application size. It’s not even an exercise on how to program a calculator or a Finite State Machine in PowerBuilder. This is really an attempt to show that PB.Net will be able to do everything that the Visual Studio developers can do with XAML and WPF, and more…

Back to the PB application: I’m not going to bloat this posting with the gory details of every event and method call. If you want to peruse the code, you can download the .Zip file containing the finished application here. But I will cover the XAML concept of Styles and Templates, which allow the PB developer to customize and extend the default GUI behavior. How about some rounded CommandButtons with a gradient background, and some animation to top it all off??

 

Step 1: Add the final four CommandButtons (BKSP, CE, C, and Enter)

The buttons we’ve placed into the application so far have been standard visual userObjects, descended from the CommandButton class. This allowed us to write some PowerScript into the ancestor classes, which are inherited by each instance that was dropped onto the gridPanel. These final four commandbuttons will just be regular WPF commandbuttons, each with one line of PowerScript in their clicked! events.

Select CommandButton from the Toolbox palette, and drop one each in the second row of grid cells (technically, Grid.Row=”1″). Stretch them to fit, and set their Margin and TextSize properties to match the other buttons in the grid. Their text property, reading from left to right, should be “BKSP”, “CE”, “C”, and “Enter”, and their names should be set to something indicative of their purpose – I named mine “cb_bksp”, “cb_clearentry”, “cb_clearall”, and “cb_enter”.

Now go into the Script window for each of them, and add the following lines of PowerScript.

cb_bksp:
parent.wf_backspace()

cb_clearentry:
parent.wf_clearEntry()

cb_clearall:
parent.wf_clearAll()

cb_enter:

//if we have only one operand, just exit
if parent.ib_eraseDisplay then Return
parent.wf_calculateResult()
parent.ib_eraseDisplay = TRUE
parent.lastOper = e_operation.none!
 
We defined the window functions that are called by these event scripts in Part II of this series. One nice new feature of PB.Net is that your PowerScript doesn’t have to compile cleanly before it can be saved, so if you haven’t already defined those window functions, you can go back and add them later! (You just can’t do a Full Build until they exist…)

 

Step 2: Define the custom templates and static resources in the XAML

Custom templates are used to define a standard look and feel for an object with a <Style> tag. Once a standard Style is defined, it can just be referenced from your controls, and they’ll “inherit” that behavior. It’s very similar to the way HTML works with Cascading Style Sheet definitions. These go into a section of the XAML called Resources, which can be “bound” to any container or control, depending on the desired scope of that reference. Since everything in our sample exists within the outer GridPanel, my XAML will create them as Grid.Resources. This example will be demonstrating three changes to the GUI of the calculator.

  1. Using ellipses as buttons, instead of plain old rectangular commandbuttons;
  2. Adding a nice shaded gradient to the background of those ellipses;
  3. Adding an animation effect to the “MouseOver” and “Clicked” events using a StoryBoard tag;

I’ve cobbled together most of the actual XAML for this from the MSDN sample itself, and John Strano’s blog post on using Custom Templates with PB.Net. Let’s get started!

 

Position the cursor in the XAML pane, right after the opening <Grid> tag on line 2, and start typing the <Grid.Resources> tag. Everything we’re adding goes inside this tag. With the shell’s Intellisense feature, all you need is the following key sequence:

<GR (tab) .RES (tab) > then enter.

Now you have a full <Grid.Resources></Grid.Resources> tag with room to enter more stuff inside.

The first thing we’ll add in there is the Storyboard tag, which defines the animation effect, and binds it to the ellipse control (which we’ll add in a moment.) That code looks like the following, and you can just copy and paste right inside the <Grid.Resources> tag.

<Storyboard x:Key="playStoryboard">
  <DoubleAnimation From="46" To="36" Duration="0:0:0.25" RepeatBehavior="1x"
AutoReverse="True" Storyboard.TargetName="TB" Storyboard.TargetProperty="(Ellipse.Height)" />
  <DoubleAnimation From="74" To="64" Duration="0:0:0.25" RepeatBehavior="1x"
AutoReverse="True" Storyboard.TargetName="TB" Storyboard.TargetProperty="(Ellipse.Width)" />
</Storyboard>

In a nutshell, this creates a Storyboard named “playStoryboard”, which animates an Ellipse named “TB”. It will shrink both the height and width by 10 pixels for .25 seconds, then return them to their original values.

 

Next, we’ll create the Ellipse style with its gradient background, and the event triggers that link to the Storyboard animation. This looks like a scary bit of XAML, but it’s not all that difficult to understand. This goes right after the closing </Storyboard> tag.  Place the cursor there and hit Enter to get a blank line, then paste the following code: 

<Style x:Key="Btn" TargetType="{x:Type pbwpf:CommandButton}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type pbwpf:CommandButton}">
        <Grid Width="74" Height="46">
          <Ellipse x:Name="TB" Stroke="DarkBlue" StrokeThickness="2">
            <Ellipse.Fill>
              <RadialGradientBrush Center="0.3,0.2" RadiusX="0.5" RadiusY="0.5">
                <GradientStop Color="Azure" Offset="0.1" />
                <GradientStop Color="CornflowerBlue" Offset="1.1" />
              </RadialGradientBrush>
            </Ellipse.Fill>
          </Ellipse>
          <ContentPresenter Name="Content" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver" Value="true">
            <Setter TargetName="TB" Property="Ellipse.Fill" Value="Aquamarine" />
          </Trigger>
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="TB" Property="Ellipse.Fill" Value="Blue" />
          </Trigger>
          <EventTrigger RoutedEvent="ButtonBase.Click">
            <EventTrigger.Actions>
              <BeginStoryboard Name="playStoryboard" Storyboard="{StaticResource playStoryboard}" />
            </EventTrigger.Actions>
          </EventTrigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

 

All this code does is define a Style named “Btn”. The style defines an Ellipse named “TB” with RadialGradient properties, within a single-celled GridPanel (because all WPF controls must exist within a container).  It then defines the event triggers for the MouseOver and Clicked events, and binds the clicked event to the Storyboard we defined earlier.  The TargetType attribute of the Style says that this Style can be linked to by any control that is a “pbwpf:CommandButton”.   Whew!

  

Step 3: Bind the CommandButton controls to the new Style resource.

The next step is to tell the CommandButtons to use the new Style.  That is done by simply adding the Style attribute to the CommandButton definitions in the XAML.  Go into each <pbwpf:CommandButton> tag in the XAML pane, and add the following attribute:

Style="{StaticResource Btn}"

You can copy that to the clipboard and just paste it anywhere inside each pbwpf:CommandButton definition.  Watch the Design Layout automatically change as each tag is altered!  Also, note that we haven’t written any PowerScript code in the Clicked or MouseMove events!  This should help illustrate the inherent separation of concerns between the XAML-based presentation layer and the PowerScript-based business logic layer. 

Here’s a screen shot of the final product! 

Finished Project

If you want to get the calculator actually calculating, you’ll need the PowerScript for the window functions, which can be downloaded from the full source code in this .Zip file

 

The Final Analysis

Since we didn’t implement all of the functionality of the original MSDN example, a true line-by-line comparison isn’t really meaningful.  But I’m going to tell you anyway.  ;)   My example in PowerBuilder.Net comes in at a svelte 94 lines of code, compared to 498 lines of C# in the MSDN sample.  I’m confident that, even if I took the time to implement the remaining functionality, I wouldn’t add 400 more lines of code…

Of course, this is Beta software, and I am seeing some Beta strangeness…  For example, the buttons inside the grid should resize themselves as the grid cells expand, and they’re not.  Also, the animation in the mouse click is not returning the buttons to their original dimensions…  At this point, I’m not sure if it’s my XAML or an issue inside PB.Net, but I’ll certainly follow up as newer builds become available.  Feel free to post any thoughts or comments…

 

Enjoy!

-Paul-

 

Oct 7, 2009

Follow-up:  I’ve solved the animation problem where the commandbuttons were returning to a circle instead of an ellipse.  If you move the Width and Height properties from the <Grid> tag to the <Ellipse> tag, you’ll see the correct behavior.  Here’s an excerpt of the revised XAML, so you can see what I’ve changed.

<ControlTemplate TargetType=”{x:Type pbwpf:CommandButton}”>
   
<Grid>
       
<Ellipse Width=”73″ Height=”46″ x:Name=”TB” Stroke=”DarkBlue” StrokeThickness=”2″>
 

 

And make sure the From and To properties in the <StoryBoard> tag are set correctly as well:

<Storyboard x:Key=”playStoryboard”>
   
<DoubleAnimation From=”46″ To=”36″ Duration=”0:0:0.25″ RepeatBehavior=”1x” AutoReverse=”True” Storyboard.TargetName=”TB” Storyboard.TargetProperty=”(Ellipse.Height)” />
   
<DoubleAnimation From=”73″ To=”63″ Duration=”0:0:0.25″ RepeatBehavior=”1x” AutoReverse=”True” Storyboard.TargetName=”TB” Storyboard.TargetProperty=”(Ellipse.Width)” />
</Storyboard>
 

 

-P-

September 21st, 2009 | Tags: , ,

In my previous post, we took a closer look at the XAML and WPF design capabilities of PowerBuilder.Net (AKA PB12), and actually began to construct a sample calculator application.  I’m using this MSDN sample as a design guide, which was 489 lines of C#, not counting the XAML.  The previous posting got us through the basics of the window and gridPanel layout, and we were just about to start writing some PowerScript to get the calculator working.  Let’s continue that discussion now!

 

Step 4: Analysis and Design work

I’m one of those developers that likes to spend some time in the Analysis and Design phase before I write any code.  Call me crazy, right??   Anyway – let’s lay out the basic design and some fundamental requirements before we jump into the Powerscript…

We know we’re going to have 11 “number” buttons – the digits 0 through 9 plus the decimal point.  There will be the four basic arithmetic operators representing “add”, “subtract”, “multiply”, and “divide”, as well as the “+/-” button representing the “negation” operation.  The remaining buttons will be “Clear”, “Clear Entry”, “Backspace”, and “Enter”.  That’s a total of 20 command buttons, plus the SingleLineEdit to present the user’s entry and the result of the calculations.  Just so we’re all on the same page, here’s a shot of the finished app, showing the design layout and a snippet of the XAML.

WPF Calculator app

 

Now, let’s take a second and think about the basic functions of an elementary calculator. 

Number buttons:

When you click a button that contains a number or the decimal point, that character is appended to the currently displayed result.  There are a few exceptions to that general rule, which are:

  • If the current display reads “0″, and the button pressed is “0″, do nothing.
  • If the current display reads “0″, and the decimal point is pressed, the next digit will go into the “tenths” place, not the “ones” place.
  • If the current display reads “0″, and a number button between 1 and 9 is pressed, replace the “0″ with the selected number.
  • If the current display is at its upper character limit, and a number button is pressed, do nothing.
  • If the current display already contains a decimal point, and the decimal point is pressed again, do nothing.
  • If the last button pressed prior to this number was an operation key, then this digit now goes into the ones column. 

Arithmetic operator buttons:

  • Add, Subtract, Multiply, Divide have no visual effect, they just set the state of the “next operation to perform”, and persist the displayed value to an instance variable.
  • The Negation button multiplies the current display by -1.  (No visual effect when the value is zero)
  • Pressing Add, Subtract, Multiply, or Divide when there’s a pending operation will calculate that result (as if the user hit Enter first).

Backspace key:

  • If the current display is a single digit, replace that digit with “0″.  (This is redundant when the digit is actually zero…)
  • If the previous button pressed was the decimal point, no visual changes are necessary, but the next digit pressed will be in the “ones” place, not the “tenths” place.

Clear button:

  • Resets the entire state of the machine, including the current display and the selected operation. 

ClearEntry button:

  •  Erases the visual display, but the currently selected operation and the

Enter button:

  • If an arithmetic operation has been requested, Enter performs that requested calculation on the currently stored intermediate result and the value being displayed.

 

Step 5: Write some Code!  Add the Window functions in Powerscript

With the basic requirements as outlined above, I envision the need for six basic window functions:

  1. wf_appendDigit( integer ai_digit )
  2. wf_requestOperation( e_operation ae_Operation)
  3. wf_backSpace()
  4. wf_clearAll()
  5. wf_clearEntry()
  6. wf_calculateResult()

(Sound of brakes squealing…)   Hold up – what exactly is the datatype of the argument in #2 above?  e_operation?  That, my friends, is a custom enumeration!  With PB.Net, you now have the capability to define your own enumerations, and they behave exactly like the built-in system enumerations you already know and love – like dwItemStatus (New!, NewModified!, NotModified!, etc..)  So let’s define a new enumeration for our arithmetic operations!  For the uninitiated, enumerations allow you to refer to a name/value pair by its name, so you don’t have to remember that “add” is option 1, and “subtract” is option 2, and so on.  Makes your code MUCH more maintainable.

File > New…  and select Enumeration from the PB Object node as the item to create.  In the next window, give it a name (e_operation), and then click Finish.  What you’ve created in the painter is a set of name/value pairs.  PB stores them internally as integers, but that’s not really important… You refer to them in your code as e_operation.Add

Enumeration Painter in PB.Net 

 

Instance variable definitions in the Window w_wpfCalc class:

Private:
e_operation lastOper   // Reference to the custom enumeration
decimal     id_lastValue
boolean     ib_decimalRequested=FALSE
boolean     ib_eraseDisplay=FALSE
integer     ii_displayLengthMax=10
 

 

Step 6:  Create the commandButton UserObject hierarchy

One of PowerBuilder’s strengths has always been its Object-oriented capabilities.  With OO inheritance, any behavior  defined in an ancestor class gets automatically inherited by its descendents.  Well, in looking at the 20 commandbuttons I have to define for this calculator app, sixteen of them fell into one of two basic groups – digits (zero through nine and the decimal point) or operators (add, subtract, divide, multiply, and negate).  Clear, ClearEntry, Backspace, and Enter have unique processing requirements.

So let’s define ancestor classes for digits and operators, and we’ll have that much less coding to do in the window itself.  Here’s a shot of the File > New… dialog, where you request a new Visual User Object, descended from the CommandButton system class.

File New dialog - inheriting from system classes

 

u_cb_digit:

Instance variables:
       
integer myDigit

Clicked Event script:
        parent.DYNAMIC wf_appendDigit( myDigit )

u_cb_operator:

Instance variables:
       e_operation myOperation

Clicked event script:
       parent.DYNAMIC wf_requestOperation( myOperation )

One last thing, to resolve a simple bug I’ve found in this Beta build.  Our code will be overriding the PBHeight and PBWidth properties of these button classes in the descendents.  I’ve found that the window painter does not respect those changes, and resets commandButton userobjects to the same PBHeight/PBWidth that is coded in the ancestor class.  To workaround that problem for now, set these properties in the XAML of both u_cb_digit and u_cb_operator:

PBWidth="334", PBHeight="184"  

 

Step 7:  Drop the UserObjects and CommandButtons into the GridPanel

Now we place the CommandButton classes onto the window, and position them within their gridPanel cells.  The key to this step is to remember that we need to select UserObject from the toolbox palette for the numbers and operators, not CommandButton.  Backspace, ClearEntry, Clear, and Enter will be normal CommandButton classes. 

 Start in the lower left hand corner.  That’s where the “0″ key will go.  Hover over the “Toolbox” icon in the upper right portion of the screen (if you closed it by mistake, and it’s not there, select View > Toolbox to bring it back).  I like to use the “pin” icon to keep the toolbox from auto-hiding while I’m using it… 

Select the UserObject tool, and then click into the cell in the lower left hand corner.  For future reference, that’s Grid.Column=”0″ (which is the default, so it won’t appear in the XAML), and Grid.Row=”5″.  As soon as you drop the control, you’ll be prompted to select the UserObject ancestor class.  We want u_cb_digit.  PB.Net is going to place the control somewhat below and to the right of where you clicked (it is Beta software, so this might be a defect).  Just drag it back into position and then stretch it to the edges of the cell. 

Change the following properties either in the properties panel, or directly in the XAML:

Margin=”4″ (which is the equivalent of “4,4,4,4″), Name=”cb_0″, Text=”0″, TextSize=”-16″

Add the following code into the Constructor event of cb_0 (you get here by selecting the window labelled “w_wpfCalc : Window [Script]“ at the top, then selecting cb_0 and the Constructor event:

this.myDigit = 0

 

Now place a button into the cell in Column 1, Row 5.   This is going to be the “+/-” or cb_negate key.  Select the UserObject tool from the palette. But this time, choose u_cb_operator as the ancestor class.  Position the button appropriately inside the cell.  NOTE: the automatic gridlines that appear will help, by snapping to the same dimensions as the button to its immediate left. 

Change the following properties:

Margin=”4″, Name=”cb_negate”, Text=”+/-”, TextSize=”-16″

Add the following code into the Constructor event of cb_0 (you get here by selecting the window labelled “w_wpfCalc : Window [Script]“ at the top, then selecting cb_0 and the Constructor event:

this.myOperation = e_operation.negate!

See how cool those custom enumerations are!!  

 

Continue through the grid, placing the appropriate UserObjects into their corresponding cells.  Use the first image above as your design guideline.  In the Constructor events of commandbuttons cb_1 through cb_9 (the descendents of u_cb_digit) add the following line: 

this.myDigit = (its number, one thru nine)

We’ll use “this.myDigit = 10″ for the decimal point key.  The descendents of u_cb_operator will get similar code in their Constructor events:

this.myOperation = e_operation.<add!, subtract!, multiply!, or divide!>

 

In the 3rd and final posting, we’ll add the four regular CommandButtons at the top, and get this application deployed and running!!

 

Enjoy,

-Paul-

September 18th, 2009 | Tags: , , ,

PowerBuilder.NET (aka PB12) is due out in the first half of 2010, and is currently out in public beta testing.  One of the fundamental goals of PowerBuilder, since its introduction in 1991, is to abstract out the technical tedium of Windows application development, and to free developers from having to worry about the “nuts and bolts”.  It was true when we were building Windows 3.1 apps, and it still holds true for the next-generation, which is Windows Presentation Foundation (WPF).  PB.Net will bring PB developers into the new world of WPF programming, introduce them to Extensible Application Markup Language (XAML), while maintaining the familiar “PowerBuilder” coding experience and requiring a minimum investment in retraining.  (Oh, and existing PowerBuilder Win32 applications should migrate to WPF with little or no modification…)  A fairly tall order, but early looks at the public beta for PB12.NET are getting a lot of positive press!!

Even with all that R&D effort, veteran PB developers taking the leap into PB.Net will be faced with some new concepts, not to mention a brand new IDE. PB.Net will be delivered in the Visual Studio Isolated Shell. Microsoft has stripped down the Visual Studio IDE to its bare-bones, and made that shell available to software vendors (like Sybase) to plug in their specific programming languages. Sybase will be one of the first vendors to embrace this new paradigm, and Microsoft is partnering very closely with Sybase to help ensure a successful launch.

Here’s a sneak peek of that new IDE, which shows that all the familiar features of the PB IDE still exist, they’re just enhanced with the features inherent in the Visual Studio IDE.

PB12 in the Visual Studio Isolated Shell

PB12 in the Visual Studio Isolated Shell

Everything that existed in earlier releases of PB will have a counterpart in PB.Net – including the System Tree, the output pane, the toolbox/palette, and the properties panes.  Notice that the layout designer is split into two halves.  The top half is the WYSIWYG drag-n-drop editor that PB developers have known for years.  You select a control from the toolbox, drop it on the surface of the window or container, set its properties, and code its event scripts.  What’s new is the bottom half of the screen – the XAML code pane, where you can edit the XAML directly.  Changes that are made in the designer or the properties pane are immediately reflected in the code pane, and vice versa. 
One nice new feature for PB developers will be instantaneous feedback of errors.  If the editor detects a syntax error, you’ll get that curly red underscore that highlights the problem code as you’re typing.  There’s also code block collapsing and Intellisense, courtesy of the VS Shell.  But the fact that XAML is an industry standard, means that you can assign the graphic design tasks to, say, a graphic designer, and that XAML can then be pasted directly into the editor pane.

But the best way to learn the editor is to take it for a spin, so over the next several blog posts, I’ll implement a WPF sample calculator app  from the MSDN.  To keep things focused, let’s get through the visual UI design first, then worry about writing the Powerscript.  The C# sample on MSDN is 489 lines of C# code - which doesn’t even take the XAML into account!  We’ll see what that looks like in PB.Net.

 

Step 1:  Create the Solution, Target, and Window

What was called a “Workspace” in prior versions of PB, is now called a “Solution” in PB.Net (to more closely correspond with the Visual Studio environment.)  The process is essentially the same.  You select File > New…  to open the dialog, then give your Solution a name and a folder location.  Solution files are given a .PBWX extension.

Once the Solution is created, you create a new Target with the same File > New… selection (or right-clicking on the Solution in the Solution Explorer/System Tree), but now you select the appropriate Target type from the three options presented.   We want a WPF Window Application.  The other two choices are .Net Assembly and .Net Web Service, but we’ll look at those later on.

File New dialog 

The Wizard walks you through the creation of the Application and Target (which now have a .PBTX extension), and the initial Project object.  I named this example PBCalc.  The rest of the Wizard consists of pages for external resource folders (.ICOs, .BMPs, etc., ), executable filenames, and whether to publish as a SmartClient app.  Just take the defaults and create the target.  Now it’s time to create our first WPF window.  Select File > New… to bring up the same dialog, with a bunch of new selections.  Expand the PB Object node, and select WPF Window.

File New dialog

The next step in this Wizard asks for a Window Title – “WPF Calculator”, and a window name – “w_wpfCalc”.  Press Next to continue.

Now for an important decision – which container style to use for the WPF window?  There are five available choices, as described in my previous post about container styles.  We’ll just take the default Grid, because none of the other layout styles fit our requirements.  We could have used Canvas, but that requires you to place each button at exactly the X/Y coordinates that you want.  It would work, but would introduce a maintenance headache down the road…

  Click Finish to open the Window painter and start the development ball rolling!

 

Container selection

Step 2: Design the Window surface using the XAML Layout pane

The first major difference between the classic PowerBuilder IDE and PB.Net is that both the WYSIWYG layout designer and the code that implements that layout are visible at the same time.  In PB.Net, there’s a horizontal splitbar separating the layout designer from the XAML pane in the same window.  What you’ll see when you click Finish is a window definition (the pbwpf:Window tag) for our WPF Calculator, with an empty Grid panel inside it. The Powerscript window (where you write functions and event scripts) is on a completely separate tabpage labelled “[Script]“.  

PB12.NET XAML painter

Since we’re focusing initially on the screen layout, let’s start by adding some row and column definitions into the Grid panel. The easiest way to accomplish this is to select the Grid panel, then position the mouse in the small area between the edge of the Grid and the window border.  You’ll see a gridline appear inside the grid, and it will place itself permanently when you click the left mouse button.  Our calculator will require a 4X6 grid, for a total of 24 cells.  Here’s what you’ll see after you place the four vertical gridlines.

Grid - step 1

Watch the XAML pane as you click in the visual painter.  You’ll see PB.Net building the ColumnDefinition tags right before your eyes…  Should you make a mistake and add an extra column, it can be deleted it by simply dragging the icon from the header (that little orange triangle) off the surface of the grid.  Or, you can just edit the XAML directly and delete the entire ColumnDefinition tag.  

Notice that the grid columns aren’t evenly sized either.  The behavior we’d like is for them to resize themselves automatically as the window changes shape, but it’s hard to get that exactly right with the mouse.  Well, look at the Width parameters in the XAML.  The number part indicates the initial size, and the trailing “*” indicates that the cells should resize with the Grid.  If we want them evenly spaced, just remove the integer parts so that the Width parameter is simply “*”.

Now create a RowDefinition tag by clicking in the vertical border area to the right or left side of the Grid. Just do one for now, and place it anywhere along the side of the Grid.  PB.Net will create two RowDefinition tags in the XAML. 

Edit the Width property of both tags and change it to “*” – the horizontal gridline will reposition itself to the center of the grid automatically.  And just so you can truly appreciate the power of direct XAML editing, copy one of the RowDefinition tags to the clipboard, then paste it below the existing tag four more times, for a total of six.  The final result should look something like this:

Finished Grid panel

 

Step 3: Place the Button and SingleLineEdit controls inside the Grid

In this step, we’ll add one SLE control and 20 CommandButton controls to the grid, and our calculator will start taking shape.  The key to working with a grid is to understand that the row and column numbers start at 0, not 1.  Let’s place the TextBox into row 0 of the grid, and set it to span all four columns.

Hover your mouse over the ToolBox widget in the upper right-hand corner, and it will magically slide into view.  Clicking the “pin” icon will cause it to stay in place, otherwise it will close when the mouse moves away.  Click the TextBox control, and then click the mouse into the upper left-hand cell of the Grid (row 0, column 0).  An SLE control appears in the cell with all sorts of arrows and icons surrounding it, and the pbpwf:SingleLineEdit tag gets created in the XAML.  The Grid.ColumnSpan attribute defaults to “2″ – change it to “4″ in the XAML, or just drag the SLE wider until it touches the right-hand wall of the grid (in column 3).  In either the XAML or the properties panel, change the name to “sle_result”, the taborder to “0″, and the text to “0″.  

Change the TextAlignment property to Right, and the TextSize to 18.  This can either be done in the Properties pane, or in the XAML itself.  The Intellisense feature will auto-select the property as soon as you’ve typed enough characters for it to recognize it.

Notice the Margin property.  It’s some seemingly random collection of four comma-separated digits.  These indicate the size of the area between the left, top, right, and bottom edges of the control to its immediate container – in this case that would be the RowDefinition element.  Change that property to “4,4,4,4″ and see how that looks.

Lastly, to help differentiate the background of the result SLE from the window itself, let’s change the window background color to blue.  Position the cursor in the XAML pane right before the closing “>” character of the Window tag. It should be the one on line 6, just before the <Grid> opening tag.  Press the spacebar to initiate Intellisense, then “B” to select the first property that starts with “B”, (which happens to be “Backcolor”), then TAB to select the property and position the cursor in the attribute value.  Press “B” to select the colors that start with B, then scroll down to select “Blue”.  It’s that easy! 

It should look something like this:

PB12.Net calculator grid

I’ve written enough for this post, so we’ll continue in the next installment with the commandButtons and the PowerScript and get this calculator working!

 

Enjoy!

-Paul- 

September 3rd, 2009 | Tags: , , , , ,

By now, everyone on the planet knows what an iPhone is, and either has one or wants one…  The only real weakness of the iPhone centers around its capabilities as an Enterprise business device.  Here’s a great review of the iPhone 3Gs as an “Enterprise” device by Jason Hiner, of TechRepublic.  Jason is a great writer, and I follow his blog religiously.  This article is a thorough evaluation of the plusses and minuses of the iPhone, and Jason’s “bottom line” is this:

It’s a great device, but:

  • Hard to do a lot of typing on because of its on-screen keyboard;
  • AT&T is the sole carrier in the US, and their network coverage here can be spotty;
  • Not nearly as secure as a Blackberry and their BES server;

Couldn’t agree more.  Especially that last point.  Consequently, I see a lot of people carrying two (or three) devices!  They use the Blackberry for corporate e-mail, calendar, and PIM, and an iPhone for everything else.

But there’s an answer!  With iAnywhere Mobile Office, you not only get your Exchange or Lotus Domino corporate e-mail, but you get Enterprise-level security features! Features like poweron passwords, remote wipe/kill/restore, and full data encryption.  In addition, the IT department will LOVE the over-the-air provisioning, and centralized management and control, and automatic software updates.

But Mobile Office doesn’t stop there!  With iAnywhere’s innovative “Business Process Widgets”, you can extend selected business processes out to the mobile device!  Imagine being able to approve or reject a critical purchase order, authorize a vacation request, file your time/expense reports, right from your iPhone, without having to log on to the corporate network and access the ERP or HR system.    Widgets are delivered as e-mail attachments, and can be acted on immediately upon receipt.  The image below shows a Windows Mobile image of Mobile Office inbox.

iAnywhere Mobile Office

Another benefit of iAnywhere Mobile Office is that YOU have the option of managing and controlling your own corporate data.  If you choose to, you can run the Mobile Office server on your hardware, in your data center!  It’s not being hosted on a server somewhere out in the “cloud”, out of your control.  When the Blackberry service suffers an outage, it takes ALL its users down with it, and you’re at their mercy to fix it.  As an added layer of security, iAnywhere offers a “Relay Server”, which gets installed into the DMZ and eliminates all inbound TCP/IP connections through the corporate firewall.   Here’s a white paper describing the security features of Mobile Office for the iPhone.

If you’re tired of being chained to the Blackberry by your IT department, and would like to use your iPhone for 100% of your mobile needs, you owe it to yourself to check out iAnywhere Mobile Office.

Enjoy!

-Paul-

TOP

Bad Behavior has blocked 90 access attempts in the last 7 days.