This article was brought to you by the guys from VDF-GUIdance.
For more DataFlex targeted articles see http://www.vdf-guidance.com


Interactive XAML with codejock

by Wil van Antwerpen

Summary

This article discusses some methods on how to make your codejock XAML objects interactive.
Unfortunately at this time there are some limitations in what you can do, but I hope that this how-to will help in discovering better and more complete methods for doing this.
Size: 14 KB Download
Date Created: 03/17/2018
Date Updated: 03/17/2018
Author: Wil van Antwerpen
Company: Antwise Solutions


Introduction



This article discusses some methods on how to make your codejock XAML objects interactive. We are basing our code on the code from the UKSig group and have added two new views.

Unfortunately at this time there are some limitations in what you can do, but I hope that this how-to will help in discovering better and more complete methods for doing this.

The problem case



The documented solution by codejock for how you can act on your XAML components is by using so called routed events.

As it is, I have not been able to use routed events from within DataFlex. The only way I was able to use that technique was by wrapping the codejock xaml components into a C# .net activex control and then consuming those activex control wrappers from within DataFlex.
That by itself had some other issues (focus runtime errors) and I discarded that solution for another non codejock one after that experience.

So you could already use XAML, but as it was you could not act on mouse clicks, until now.

The solution I am describing here just uses DataFlex and the full codejock suite. It was developed end of last year when a customer of mine wanted to develop a very fancy grid with each of its cells rendered via xaml.

That turned out very well and I figured that I had cracked all of the issues. Unfortunately that is not the case. What I could do for the xaml enabled grid cannot be done for the standard "label" example as in the SIG UK example. I did however find a -somewhat ugly- workaround.

Interact with Xaml in a codejock grid



The code I'm showing here is very bare bones, it is a grid with only 1 cell -just 1 column and 1 row.
In addition it uses one of the standard xaml files from the sig cj group demo to show how it works. It does not make much sense from that point of view, I just picked a random xaml file.

First problem and main problem in the parts I currently have been unable to fix: catch a mouse event.

In the grid what I am using is simply augmenting event OnComMouseUp and then using a fairly simple HitTest to see if the cell I need was clicked upon. If that's the case, we trigger a OnItemClick message.

With that out of the way we can at least detect that we are clicking on the xaml object.

Next up is figuring out what actual xaml object we are clicking on.
This is done in two steps. The first one is by adding a name to the object in the xaml that you want to access mouse clicks for.

In our xaml example we have
<TextBlock HorizontalAlignment="Left" Cursor="Hand">Drafts</TextBlock>


and if we want to be able to access clicks on that TextBlock element then we need to add a Name identification for that element, for example:
<TextBlock Name="Drafts" HorizontalAlignment="Left" Cursor="Hand">Drafts</TextBlock>


Then in our new OnItemClick we can find that object and test if it has the mouse over it (as we just clicked... that means we clicked on that item (hurray!))

Basically in code it looks like:
      Boolean bIsMouseOver
      Handle  hoMarkupObject
      Variant vMarkupObject
      
      Get ComFindName of hoMarkup "Drafts" to vMarkupObject
      If (IsComObject(vMarkupObject)) Begin
        Get Create (RefClass(cSigCJComMarkupUIElement)) to hoMarkupObject
        If (hoMarkupObject) Begin
          Set pvComObject of hoMarkupObject to vMarkupObject
          Get ComIsMouseOver of hoMarkupObject to bIsMouseOver
          If (bIsMouseOver and iMessage<>0) Begin
            Send info_Box "Drafts was clicked!"
          End
          Send Destroy of hoMarkupObject
        End
      End


The hoMarkup object is an object that is retrieved from the MarkupUIElement of the report cell.

That pretty much is it (yes, there's a bit more code to it, but you can see that for yourself in the codejock example view, which you can find in file: SigCJXamlInteractiveDemo.vw

You can click on drafts/inbox/sent/junk and get the appropriate popup telling you what you clicked.

Interact with Xaml in Label control



This one is a bit of a problem and it is mostly about catching the mouse click event. Something basic one would think.

There are two versions of the Xaml Label control.

The default one that is used in the UK Sig codejock example is: cSigCJLabel
The one I ended up using is: cSigCjComMarkupLabel

The cSigCJLabel control actually does catch the mouse event just fine, but it does not expose the markupUIElement that we need to connect towards.

The cSigCjComMarkupLabel control never sees a mouse event, but it does expose the markupUIElement just fine.

This looked like it was a bit of a mutual exclusive event, but I managed to track when users click into the control by catching a OnEnterObject instead and then sending a "Fake_Mouse_Up" event based on that. This one should be called a hack as a keyboard event can also trigger an OnEnterObject and there's no way to identify if it was a mouse click or keyboard event that triggered it.
So I'm hoping for somebody to find a better technique for this part.

For the rest the technique is pretty much the same as with the grid. In this case I only connected the draft and junk folders of the outlook pane.

You can view the code in: SigCJXamlInteractiveDemoLabel.vw

In this demo you can click Drafts or Junk (I did not connect the other ones) to see what you clicked.

what can it do and what isn't working yet?



Well you can act on clicks on any text or image object, which with a bit of creativity does open it up for a bit.

Things that are currently invisible to our clicks are:
  • radio controls
  • hyperlinks
  • buttons
  • ... probably some more controls

So we're certainly not exactly there yet.

All of this was tested with Codejock 16.3.1 and I wouldn't be surprised if it works better in later codejock revisions, but this is what we are currently using.

As all we use in xaml in our project works fine I have to stop researching this for now.
Perhaps at a later time this can be revisited and me (or maybe somebody else) will find the solution for the open questions.

But at least this is a start and it unravels some of the parts on how it all fits together.

Download



interactiveXaml.zip ~15kB

Note that for Codejock 16.3.1 you will have to fix a typo in the UK Sig wrapper file SigCJW_MarkupLabel.pkg line 372:
    Import_Class_Protocol cComIMarkupGlobalSettings

should be:
    Import_Class_Protocol cSigCjComIMarkupGlobalSettings


This is fixed in later UK Sig codejock wrappers.

In order to test this yourself you must first install and download the full codejock suite and the UK Sig demo (see: https://support.dataaccess.com/Forums/forumdisplay.php?28-VDF-SIG-Codejock-Library ) The zip file above is then copied into that demo workspace.