Welcome!

PowerBuilder Authors: Dan Joe Barry, Ian Thain, Yakov Werde, Paul Slater, Bruce Armstrong

Related Topics: PowerBuilder

PowerBuilder: Article

Debugging DataWindows - Live!

Debugging DataWindows - Live!

You stumble on a bug in your application. In order to troubleshoot it you need to see the raw data inside your DataWindow but the columns you need aren't visible. ... You open a window in your application, and even though you don't change any of its data it still prompts you to save when closing. What has changed? ... A drop-down DataWindow isn't displaying the right values at runtime, but it retrieves just fine when you preview it at design time. Where's the data? ... You're pulling your hair out trying to get some modify/describe syntax to work, and it's taking forever between changing your code, saving and rerunning your application. Can you possibly get the syntax right and still get home on time?

The solution to all of these problems can be found in the PFC DataWindow properties dialog - after we make some enhancements, that is.

The DataWindow Properties Dialog
The PFC originally included a DataWindow debug window, which I found very helpful. With the major changes that came in PFC 6.0, the debug window was replaced by the DataWindow properties dialog, which both added and removed functionality. (I needn't mention PFC 7.0 because of the paucity of changes.) One thing I like about the PFC 6.0 dialog is that it's easy to add new debugging capabilities simply by extending existing tabs and adding new tabs. In this article I'll describe a useful enhancement to some existing DataWindow properties tabs, which essentially restores a PFC 5.0 feature that was removed in PFC 6.0. In addition, we'll add two new DataWindow properties tabs: a drop-down DataWindow tab and a Modify/Describe tab.

But first, if you aren't familiar with the DataWindow properties dialog, then obviously you don't know what you're missing! In order to access the dialog you must enable the "property" service. You can do this either by calling of_SetProperty or of_SetSharedProperty. I call of_SetSharedProperty because with one call I instantiate a shared service (referenced with the shared variable snv_Property), which makes the service accessible to all DataWindow controls in the entire application. (The function of_SetProperty, on the other hand, instantiates the same service but stores the reference in an instance variable so that it's accessible only to the current DataWindow control.) After the service is instantiated at runtime, you can right-click on your DataWindow control and the "DataWindow Properties..." option will be visible in the popup menu (see Figure 1).

Selecting the "DataWindow Properties..." option will open the DataWindow Properties dialog and its Services tab page, as in Figure 2. (Note: These figures show the DataWindow properties dialog after making the enhancements in this article.) I rarely use the Services tab, but I frequently use the "Buffers" and "StatusFlags" tabs (see Figures 3 and 4, respectively). Try them out. They're both pretty self-explanatory, and there's even on-line PFC help!

Now that I've finished explaining the "standard" way to open the DataWindow properties dialog, I can wink and nod and tell you how I really open it. The problem I have with calling of_SetSharedProperty or even of_SetProperty is that they both enable a menu option in a popup menu that users have access to. I don't want my users saying, "I wonder what that DataWindow Properties' thingy does?" So I coded a secret key sequence that opens the DataWindow properties dialog. To maintain secrecy, I'll include a simplified version here.

Open u_dw and insert a new event called "KeyDown," mapped to the pbm_dwnkey event ID (see Figure 5). Then add the following code to that event:

// Event KeyDown:
// If you press Shift-Ctrl-Alt-D, the //DataWindow property window will
// display
if Key = KeyD! and keyflags = 3 and
& KeyDown (KeyAlt!) then
// Turn on the property service for // all DWs.
this.of_SetSharedProperty // (true)
this.Event pfc_Properties ()
end if
// End if the User hit the // right key combo.

return 0

With this code in u_dw you won't have to write any additional code to access the DataWindow properties dialog, and your users won't have easy access to it. All you have to do is set focus on your DataWindow control, hit Shift-Ctrl-Alt-D and the DataWindow properties dialog will open!

Now that we're all at least vaguely familiar with the DataWindow properties dialog, let's add some cool debugging capabilities.

Extending the Buffers and StatusFlags Tabs
Some useful features were lost when the PFC 5.0 DataWindow debugger became the PFC 6.0 DataWindow properties dialog. One that I used quite frequently was the ability to view all of the raw data in any DataWindow. Notice in see Figures 3 and 4 that there are radio buttons labeled "Original" and "All Columns" - those options aren't available in the base PFC. These figures show the original view, which uses the same DataWindow object that your user sees. Notice in Figures 6 and 7, however, that every column's data is visible and editable. That's what allows me to peer inside any DataWindow's data, and it's all at runtime!

Let's start by extending the Buffers tab. The GUI is quite simple, but the code is fairly involved.

  1. Open u_tabpg_dwproperty_buffers.
  2. Add two radio buttons(rb_original and rb_all) at the bottom of the DataWidow.
  3. Set the radio buttons' text and default rb_original to checked.
  4. Shrink the DataWindows to make room for the radio buttons.
  5. Place an invisible group box around the radio buttons. (This step is optional, but it's good technique.)
  6. Write the following code for rb_original.
    parent.Event pfc_PropertyInitialize (inv_attrib)
  7. Write the code for rb_all (see Listing 1).
  8. Save and close the tab page. (Note: I had to regenerate pfc_w_dwproperty and w_dwproperty because otherwise I got a runtime error.)
The steps are the same for the StatusFlags tab, but the code for rb_all is slightly different. One difference is that this tab page has only one DataWindow (dw_requestorview), and the second difference is that this tab page has no radio buttons for selecting which buffer to display. Basically, the code for rb_all is identical to what is on the Buffers tab, except that the following two sections need to be removed.

  1. The code that refers to dw_requestor-duplicate:
    dw_requestorduplicate.Create(ls_dw_syntax,ls_error)
    if len(ls_error) > 0 then
    MessageBox("Create:",ls_error)
    return
    end if
    idw_Requestor.ShareData(dw_requestorview)
  2. The code that refers to the buffer radio buttons:
    if rb_primary.checked then
    Parent.Event pfc_PropertyBufferChanged(Primary!)
    elseif rb_deleted.checked then
    Parent.Event pfc_PropertyBufferChanged(Delete!)
    else
    Parent.Event pfc_PropertyBufferChanged(Filter!)
    end if
Finally, some limitations to this implementation of the "All Columns" radio button are worth noting.
  1. The code for rb_all assumes that the DataWindow uses SQLCA as its transaction object, which may not be the case. If needed, you can extend u_dw and add an of_GetTransObject.
  2. As noted in the code, the section of code that replaces retrieval arguments doesn't work with all DBMSs. Different DBMS vendors have different formats for some data types, and datetime values are what I've had problems with in the past. In my own framework (the NewMedia PFC) I use different formats depending on the DBMS.
  3. Even though the Buffers tab displays data from the Filter! and Delete! buffers, editing that data won't actually change data in the main DataWindow.
  4. The "Original" and "All Columns"don't view display drop-down DataWindows.

Regardless of these limitations, the Buffers and StatusFlags tabs are my most frequent reason for using the DataWindow properties dialog. The ability to see the raw data inside a Data

The Drop-Down DataWindow Tab
I can safely say that half of the DataWindows in my applications include drop-down DataWindows. That's probably pretty common. For the most part, using drop-down DataWindows is quite straightforward. But we spend very little time debugging straightforward things. The reason I created a drop-down DataWindow properties tab is because there are many occasions in my applications where dropdowns are filtered for one reason or another. Unfortunately, there have also been occasions where those filtered drop-downs don't display the expected values. The drop-down DataWindow tab in Figure 8 permits me to see inside my drop-downs. The tab page's GUI is not too difficult. It's based on the Buffers tab page, which is the second tab in the DataWindow Properties dialog. The master DataWindow lists all the drop-downs in the DataWindow being debugged. The detail DataWindow displays the contents of the selected drop-down DataWindow. Then there are radio buttons for selecting which buffer to display, and buttons for sorting and filtering. Because it's based on the Buffers tab, you can start by saving the Buffers tab under a different name. Open pfc_u_tabpg_dw-property_buffers in PFCUTIL.PBL and save it as u_tabpg_dwproperty_childdws in PFEUTIL.PBL. (Actually, mine lives in an extension layer between the PFC and the PFE.) >

Then make the following changes to the GUI:

  1. Change the GUI by deleting the extraneous controls in the group box.
  2. Add the "Child DataWindow:" text above the detail DataWindow.
  3. Resize and rearrange the controls to make room for the master DataWindow (note that there are actually two detail DataWindows - one is for displaying the Primary! buffer, and the other is for the Filter! and Delete! buffers.).
  4. Add the "Drop-down DataWindow Columns:" text at the top of the tab page.
  5. Add the master DataWindow (dw_children, based on u_dw).
  6. Create an external grid DataWindow object named d_dwproperty_childdws that has two char(40) columns ("colname" and "dataobject").
  7. Set the DataObject property of dw_children to d_dwproperty_childdws.
  8. Delete the Undelete button.
And now for the code. Declare an instance variable of type dwBuffer called idwb_CurrentBuffer. This will keep track of the selected buffer (Primary!, Filter! or Delete!).

Insert a new function called of_LoadChild, which takes a row (al_row) as its argument. This function will load the selected child DataWindow object into the detail DataWindows and refresh the view (see Listing 2).

The tab page will already have code in the following events: pfc_PropertyBufferChanged, pfc_PropertyInitialize, pfc_PropertyOpen, pfc_PropertyStats and pfc_PropertyUndelete. You can delete the code from the pfc_PropertyInitialize and pfc_PropertyUndelete events. Then make the following changes:

  1. Change pfc_PropertyBufferChanged by deleting all references to cb_undelete.
  2. Change pfc_PropertyStats to the code in Listing 3).
  3. Use the script in Listing 4 for pfc_PropertyPopulate.
  4. Add the following code to the master DataWindow's RowFocusChanged event:
    // Event RowFocusChanged:
    // Load the newly selected child DataWindow.
    return parent.of_LoadChild (currentrow)
  5. Change the code for dw_requestorduplicate by deleting all scripts except for the constructor event and set the tab page's Text property to "DDDWs" on the General tab. And that's it for the tab page! But in order to use it you'll have to add it to the DataWindow properties tab control.
Close and save the tab page, then open u_tab_dwproperties in PFEUTIL.PBL. Right-click near the top of the tab and select "Insert User Object" (see Figure 9). Select u_tabpg_dwproperties_childdws and click OK. On the General tab of the Properties pane, name the tab page "tabpage_dddws." Close and save the tab control. Done! Now you can run your application and test it out. (Note: Once again I had to regenerate pfc_w_dwproperty and w_dwproperty. Otherwise I got a runtime error.) Don't forget to set focus on your DataWindow and type the Shift-Ctrl-Alt-D shortcut to display the DataWindow Properties window.

The Modify/Describe Tab
The power of Modify and Describe never ceases to amaze me. But occasionally I have a lot of trouble getting the syntax to work as I'd like. (And I suspect I'm not alone in that experience!) In these situations the PowerBuilder debugger is rarely helpful, and the DataWindow painter isn't always helpful either. Then one day a light went on and I realized how easy it would be to build a Modify/Describe debugging tab. It took very little time to build, as you'll see, and it can be quite helpful.

Create a new tab page by inheriting from u_tabpg_dwproperty_base in PFEUTIL.PBL. The most difficult part about constructing this tab page is the GUI (see Figure 10). Make it the same size as the other tabs (1198x1200). Add some text controls, a couple of multiline edits (mle_syntax and mle_result), few buttons and an edit mask (em_position). Don't forget to inherit from base PFC controls! Finally, set the Text property on the tab page's General tab to "Modify."

The code couldn't get any easier. Here's the code for the Modify button:

mle_result.text = idw_requestor.Modify ( &
mle_syntax.text)
Here's the code for the Describe button:
mle_result.text = idw_requestor.Describe ( &
mle_syntax.text)
And here's the code for the Go to button:
mle_syntax.SelectText (Integer (em_position.text), 0)
mle_syntax.SetFocus ()
The purpose of the Go to button is to help in those situations when you get an error message from your Modify/Describe call such as "Line 1 Column 14: incorrect syntax." The line and column numbers are sometimes useful, but a more advanced "Go to" that accepted a line and column number would be more useful.

Save the tab page as u_tabpg_dwproperties_modify, close the painter and add it to u_tab_dwproperties just as before. (Don't forget to regenerate pfc_w_dwproperty and w_dwproperty!)

Closing Thoughts
Probably the biggest benefit from using a framework such as the PFC is productivity gains from code reuse. But why shouldn't your framework also help you debug and troubleshoot problems? So I hope you find these enhancements to the DataWindow properties dialog a useful addition to your PFC. And to take PFC debugging one step further, I'd suggest that you check into the debug service and SQL Spy. (How about Shift-Ctrl-Alt-S?)

More Stories By Vince Fabro

Vince Fabro is a practice leader at the Columbus branch of newmedia, a consulting firm
headquartered in Cleveland, Ohio. He's a CPD professional and certified PowerBuilder instructor who has been using PowerBuilder since version 2.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.