Using Windows Presentation Foundation (WPF) from APLX

The following Wiki page describes the use of WPF and XAML from APLX for Windows. It is based on work contributed by APLX user Pierre Gilbert, and presented here with his permission - Thanks, Pierre

Windows Presentation Foundation (WPF), is Microsoft's modern framework for creating GUI applications in .NET. It is intended to replace the older .NET framework System.Windows.Forms, which was a wrapper around the old Windows GDI interface.

WPF has a number of advantages. For example it is built on DirectX, so that richer graphics are possible and code will make use of GPU hardware acceleration. It is also vector-graphics based for resolution independence. But perhaps the most significant advantage of WPF is that the appearance of the GUI can now be specified through a new XML-based markup language called XAML. This makes it easy to create APL programs with sophsticated user interfaces.

XAML

Microsoft promotes XAML (short for eXtensible Application Markup Language, and pronounced "Zammel") when programming with WPF. It is a simple and general purpose language suitable for constructing and initializing .Net objects

The basic idea of XAML is to describe the appearance of the User Interface through a text file. This is separate to the business logic of the application, and so a XAML file can be used with an application written in any .NET language like C#, Visual Basic or - more significantly for us - APL. You can now use XAML to do all the buttons and labels stuff, add your APL code to handle the events and voila!

In addition, by using styles in the XAML file the UI can be extensively customised without changing the APL code. This is somewhat similar to the way that web pages can be customised using Cascading Style Sheets (CSS).

You can type XAML markup directly into a text editor, but for more complex examples you may want to use a tool like Microsoft's Visual Studio Express (free) or Expression Blend (free for 60 days) to write your XAML. These tools have the advantage that you can design your UI visually.

Learning XAML is not easy at the beginning and you need a good book to get you started. After a while you should be able to write the UI part of your application faster than with ⎕WI. One advantage of WPF is that you can throw the labels, buttons, etc. on one of the containers and never need to give a position or a dimension, the container will position everything for you. And if the size of the window is changed, everything is automatically resized to keep the same looks and proportions.

Advantages of using XAML

There's nothing that you can do with XAML that can't be done purely by writing code, but XAML has several major advantages:

A simple example

Here is a simple demonstration of using WPF and XAML from APLX for Windows. Although trivial it's an almost complete working example. To complete it we'll need a couple of support functions which we'll cover in a moment. You'll also need to make sure that the WPF .NET assemblies are included in the APLX .NET search path (see below).

The following XAML code will create a window containing a label and a push button:

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="XAML Demo"
   Height="200"
   Width="300">
   <StackPanel>
      <Button x:Name="myButton" Width="125" Height="35">Press Me</Button>
      <TextBlock x:Name="myText" TextWrapping="Wrap">
        I'm a text block.
      </TextBlock>
   </StackPanel>
</Window>

This produces a window which looks like this when displayed. It's a bit plain, but we'll improve it in a minute.

simple_window.jpg

Here is the APL code to load the sample XAML above from a character vector XamlString (We could also load it from a XAML text file).

Notice that the code adds an APL event handler to the button's Click event, in this case trivially appending the word "Ouch !" to the end of the text every time the button is pressed.

DEMO;root_obj;myButton;myText
root_obj ← LoadObjectFromString XamlString
myButton←root_obj.FindName 'myButton'
myText←root_obj.FindName 'myText'
⍝ Add event handlers
myButton.Click←'myText.Text←myText.Text, " Ouch !"'
Wait root_obj

Turning a XAML string into .NET objects

The function LoadObjectFromString contains the code needed to turn the XAML into WPF objects:

root_obj←LoadObjectFromString XamlString;StringReader;XAMLR;XMLR;XmlReader
⍝ Creates a WPF Object From an APL Character Vector Representing a XAML File.
⍝ XamlString = Vector of Characters
⍝ root_obj   = .Net WPF Root Object

XMLR  ← '.Net' ⎕GETCLASS 'System.Xml.XmlReader,System.Xml.dll'
XAMLR ← '.Net' ⎕GETCLASS 'System.Windows.Markup.XamlReader'      ⍝ From PresentationFramework.dll

StringReader ← '.Net' ⎕NEW 'System.IO.StringReader,mscorlib.dll' XamlString
XmlReader ← XMLR.Create StringReader
root_obj ← XAMLR.Load XmlReader

Processing Events

As the example above shows, providing an APL function to handle a .NET event is very simple. It's just a case of providing an APL expression that is executed every time the button's Click event is triggered.

myButton.Click←'myText.Text←myText.Text, " Ouch !"'

However, event handling in APLX does not fire unless the application is currently handling events. You need to call the Wait for Events system function ⎕WE. The following is a listing of the Wait support function we used earlier, which loops to handle events until the window closes.

Wait root_obj;sink
⍝ Function to Wait on a .Net 3.0 Window

sink ← '.Net' ⎕CALL 'System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop' root_obj

⍝ Show And Wait the Window
root_obj.Show

⍝ Wait while the Object is Visible
:While root_obj.IsVisible
  sink ← ⎕WE 0.1
:EndWhile

root_obj.Close

Customising appearance through XAML

We're now in a position to improve the appearance of our sample application. Note that this can be done just by changing the XAML code - we don't need to change a single line of APL (the business logic) because of the way XAML naturally separates appearance from functionality.

For this simple demo, let's improve the appearance as follows:

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="XAML Demo"
   Height="200"
   Width="300">
   <Window.Background>
      <LinearGradientBrush StartPoint="0,0" EndPoint="1.5,0">
         <GradientStop Color="#c04a52a0" Offset="0"/>
         <GradientStop Color="#ffffff" Offset="0.9"/>
      </LinearGradientBrush>
   </Window.Background>
   <StackPanel>
      <Button x:Name="myButton" Width="125" Height="35" Margin="10">Press Me</Button>
      <TextBlock x:Name="myText" FontSize="20" Margin="10" TextWrapping="Wrap">
         <TextBlock.Foreground>
            <SolidColorBrush Color="#ffffff"/>
         </TextBlock.Foreground>
        I'm a text block.
      </TextBlock>
   </StackPanel>
</Window>

Here's a screenshot of the new version:

simple_window2.jpg

OK, it's probably not the last word in GUI design! But you get the idea.

Using Styles in XAML

In our simple example above we hard-coded the font size and colour directly into the TextBlock instance. In fact, for anything except a trivial application it is better to make use of XAML's support for styles. You can declare all the important attributes of a style (e.g. font face, size, colour) in a single place, and then refer to it from elsewhere. This has the advantage of ensuring a consistent look-and-feel, and also allows you to change the appearance of the application just by updating the styles.

Search Path for .NET WPF Assemblies

WPF was initially released as part of the .NET 3.0 framework.

In order to access the WPF functions, you need to make sure that the locations of the WPF assemblies are specified in the APLX .NET search path, which you can specifying with ⎕SETUP 'using'

The following is an edited listing of Pierre Gilbert's suggested function for doing this. For the full version, which also checks that the .NET 3.0 framework is installed, see the attached workspace.

SETUP;FolderEnum;Path;SE;SWFA;path30
⍝ ADDS .NET 3.0 ASSEMBLIES TO THE SEARCH PATH
⍝ THIS FUNCTION SHOULD BE EXECUTED ONLY ONCE WHEN THE WS IS LOADED.

'Updating ⎕SETUP with Paths of .Net 3.0 Assemblies'

⍝ Path of .Net 3.0
SE ← '.Net' ⎕GETCLASS 'System.Environment'
FolderEnum ← '.Net' ⎕GETCLASS 'System.Environment+SpecialFolder'
path30 ← SE.GetFolderPath FolderEnum.ProgramFiles
path30 ← path30,'\Reference Assemblies\Microsoft\Framework\v3.0\'

⍝ Existing Paths
Path ← '.Net' ⎕SETUP 'using'

⍝ Add Reference To PresentationFramework Assembly
Path ← Path, ⊂'PresentationFramework,',path30,'PresentationFramework.dll'

⍝ Add Reference To WindowsFormsIntegration Assembly
Path ← Path, ⊂'WindowsFormsIntegration,',path30,'WindowsFormsIntegration.dll'

⍝ Add Reference To PresentationCore Assembly
Path ← Path, ⊂'PresentationCore,',path30,'PresentationCore.dll'

⍝ Add Reference To WindowsBase Assembly
Path ← Path, ⊂'WindowsBase,',path30,'WindowsBase.dll'

⍝ Add to ⎕SETUP all the Paths
'.Net' ⎕SETUP (⊂'using'), Path

'Enabling Visual Styles'
SWFA←'.Net' ⎕GETCLASS 'System.Windows.Forms.Application'
SWFA.EnableVisualStyles

'... Done',⎕R '

Sample Workspace

For further inspiration try the functions in Pierre Gilbert's sample workspace:

WPF_Part_I.aws

Here are some screenshots:

Animation Example:

demo1.jpg

Sample of WPF controls:

demo2.jpg

Font Browser:

demo3.jpg

Changing the appearance of Buttons

demo6.jpg

Learning more about WPF and XAML

Here is some useful links if you want to read more about the topics discussed:

1. Discussion about the separation of layers and XAML

2. Christian Mosers WPF Tutorial.net

3. Mike Swanson's Blog: Windows Presentation Foundation Tools and Controls

Books

I can thoroughly recommend the following book, which describes WPF and XAML in just the right level of technical detail:

Windows Presentation Foundation Unleashed by Adam Nathan (ISBN 0-672-32891-7)




Author: SimonMarsden

The Dyalog Appendix

Delving once more into the world of "real programmers", here's a partial translation (with some asides) into Dyalog. Anyone wanting to pursue XAML and Dyalog further should also look at the Dyalog Forum where Jonathan Manktelow has posted some code.

Using the same XamlString (a simple vector) as in the first example above...

DEMO;root_obj;myButton;myText
⍝ Simon Marsden's APLX example, mutated into Dyalog
 root_obj←LoadObjectFromString XamlString
 myButton←root_obj.FindName⊂'myButton'
 myText←root_obj.FindName⊂'myText'
 myButton.onClick←'#.Ow'
 root_obj.ShowDialog

Things to note here:

 root_obj←LoadObjectFromString XamlString;sr;XAMLR;XMLR;xr;⎕USING
⍝ Simon Marsden's APLX example, mutated into Dyalog
⍝ Creates a WPF Object From an APL Character Vector Representing a XAML File.
⍝ XamlString = Vector of Characters
⍝ root_obj   = .Net WPF Root Object
 ⎕USING←#.WPF.Using                          ⍝ Jonathan Manktelow's omnibus edition
 sr←StringReader.New⊂XamlString
 xr←XmlReader.Create⊂sr
 root_obj←XamlReader.Load⊂xr

Which is where the real differences show up

And, as it's a function rather than an inline expression

Ow w
 myText.Text←myText.Text,' Ouch!'

Try it in APL/W 12.1 (probably earlier versions as well) and Bob's your uncle.

Finally, I'm in a bit of a quandary here about whether this is a wholly "good" direction to take for future applications. While I can agree with Simon about hooking up with mainstream tools and getting access to all sorts of fancy interfaces I also hanker for the good old days when APL (or J) was all a person (or computer) needed.

(Simon's comment: Dick, thanks for adding the Dyalog material. Regarding your last paragraph, one point to make is that adopting XAML and WPF is entirely optional. APLX will still retain the older ways of doing things like the  ⎕WI interface, and I imagine Dyalog will continue with  ⎕WC. However, I actually think WPF is easier to use once you've got the hang of it -- SimonMarsden 2010-06-17 08:48:47)

Translator: DickBowman


CategoryDotNet CategoryAplx

UsingWPF_from_APLX (last edited 2010-06-28 13:07:11 by DickBowman)