wpfXmlBindingDemo

UNDER CONSTRUCTION

wpfXmlBindingDemo is a Dyalog APL namespace that shows examples of how to bind a XML representation of APL data to a WPF user interface.

Overview

When building a User Interface (UI) with WPF, the APLer can use Xaml or code directly with APL. Some examples of using Xaml can be found here wpfXamlDemo. Either way the data to the UI will need to be filled and it can be done again directly with APL code or with DataBinding. With APL code each element that display some data will need to be written with the value of an APL variable, with DataBinding it is possible to bind the value of an APL namespace directly with multiple elements of the UI. If the DataBinding is made bidirectional, when the user changes the data in the UI it will be changed back in the APL variable at the same time. When using only APL code, the data will need to be retrieve from each display element and saved back to the APL variable.

For binding you can use the 2015 ⌶ beam (2015⌶) from Dyalog, a .Net DataTable, a .Net XmlDocument or even a database. In all cases, the APL data will need to be converted to a .Net object so it can be used by the UI that reside on the .Net side. Some utility functions for dealing with .Net DataTable are available at netDataTable. Refer to Dyalog tutorials on how to use the 2015 ⌶ beam. This Wiki is to demonstrate the use of a .Net XmlDocument representing the APL data for binding with a WPF UI.

XML Representation of APL Data

Surprisingly, converting a large quantity of APL data to a .Net XmlDocument is as fast or faster than converting it to a DataTable because it is only characters that are passed on the .Net side (wich is very fast). However the Xml representation of the data needs to be made in such way that the XPath used in the Binding will be able to find the data but also it needs to contains all the information to revert the XmlDocument back to APL data when used with two way binding. The functions AplToXml and XmlToApl of the attached namespace are doing just that for simple APL data that is not nested. Here is some examples:

Vector:

    ⍝ Example for a vector
      {⎕XML ⎕XML ⍵.OuterXml} AplToXml 1 2 (⍳0) ('') 'some text'

<Data Rank="1" Shape="5" Type="array" xmlns="">     ⍝ 'Data' is the name of the root element.
  <n>1</n>
  <n>2</n>             ⍝ The Rank(⍴⍴), Shape(⍴) and the Type(array or namespace) are attributes in the root element
  <n></n>              ⍝ The name of the elements with the data is either <n>(for number) or <s>(for string)
  <s></s>              ⍝ The 'Elements' of the Xml are holding the data.
  <s>some text</s>     ⍝ Empty values are permitted and used for place holder. Use ⍳0 for numbers and '' for characters.
</Data>

The function AplToXml is returning a .Net XmlDocument. To see the characters the property .OuterXml is used. Typical Binding for the third element would be: "{Binding XPath=/Data/*[3]}" or for the whole vector: "{Binding XPath=/Data/*}"

Matrix:

    ⍝ Example for a matrix
      {⎕XML ⎕XML ⍵.OuterXml} AplToXml 2 3 ⍴ 1 2 'three' 4 'five' 6

<Data Rank="2" Shape="2 3" Type="array" xmlns=""> ⍝ This is the 'Attribute' style representation of the matrix
  <nns C1="1" C2="2"    C3="three"></nns>         ⍝ The name of the elements are still 'n' for numbers and 's' for characters
  <nsn C1="4" C2="five" C3="6">    </nsn>         ⍝ The column names are 'C1', 'C2' etc. by default
</Data>                                           ⍝ The 'Attributes' of the Xml are holding the data. Elements are empty

    ⍝ The equivalent 'Element' style representation is shown below for information only:
<Data Rank="2" Shape="2 3" Type="array" xmlns="">
  <Data>
    <C1 Type="n">1</C1>
    <C2 Type="n">2</C2>
    <C3 Type="s">three</C3>
  </Data>
  <Data>
    <C1 Type="n">4</C1>
    <C2 Type="s">five</C2>
    <C3 Type="n">6</C3>
  </Data>
</Data>

The 'Attribute' style was retained because it is taking less characters to write. A matrix will typically be used for a DataGrid, ListView and ListBox. The names of the columns are prefix at 'C1', 'C2', 'C3', etc. Typical binding for the first column would be: "{Binding XPath=/Data/@C1}"

Simple Namespace

    ⍝ Example for a simple namespace:

      ns ← ⎕NS ''
      ns.firstName ← ⊂'Marco'
      ns.lastName  ← ⊂'Polo'
      ns.location  ← ⊂'Venezia'
      ns.interest  ← ⊂'Travelling'

      {⎕XML ⎕XML ⍵.OuterXml} AplToXml ns

<Data Type="ns" xmlns="">
  <firstName Rank="0" Shape="0" Type="array" xmlns="">
    <s>Marco</s>
  </firstName>
  <lastName Rank="0" Shape="0" Type="array" xmlns="">
    <s>Polo</s>
  </lastName>
  <location Rank="0" Shape="0" Type="array" xmlns="">
    <s>Venezia</s>
  </location>
  <interest Rank="0" Shape="0" Type="array" xmlns="">
    <s>Travelling</s>
  </interest>
</Data>

Each properties names of the namespace will hold the data. The binding will refer to that property name in the Xaml. It is not necessary for the objects in the Xaml to have a Name or x:Name defined for the binding to work. Typical binding would be: "{Binding XPath=/Data/firstName/*}" or "{Binding XPath=//firstName/*}". This type of representation of the APL data can have a converter on the APL side (see more information below). The function demo1 in the attached namespace has a complete example for this type of binding.

Namespace within a Namespace

     ⍝ Example of namespace within a namespace

      ns ← ⎕NS ''
      ns.Books ← ⎕NS ''
      ns.Books.Author ← 'author1' 'author2' 'author3'
      ns.Books.Title  ← 'title1' 'title2' 'title3'

      {⎕XML ⎕XML ⍵.OuterXml} AplToXml ns
<Data Type="ns" xmlns="">
  <Books Rank="2" Shape="3 3" Type="nsArray" xmlns="">
    <sns Author="author1" Title="title1"></sns>
    <sns Author="author2" Title="title2"></sns>
    <sns Author="author3" Title="title3"></sns>
  </Books>
</Data>

Each properties of the namespace Books must have the same number of items. This is the typical binding for data that would be presented in a tabular form like a DataGrid or a ListView. Typical binding would be: "{Binding XPath=/Data/Books/@Author}". The function demo2 in the attached namespace has a complete example for this type of binding.
The functions AplToXml and XmlToApl are used for a two way binding, the functions has to find if each values are numeric or character. The function MatToXml can be used for one way binding of an APL matrix without checking if each values are numeric or character. It is perfect for displaying a large quantity of information on a DataGrid or ListView when there is no need to convert back the binding to APL. This type of representation of the APL data can have a converter on the APL side (see more information below). See the function demo3 for an example.

About XPath

If you are not sure of the syntax for XPath you can always use the function XmlDocToFile included in the attached namespace to write the XmlDocument to disk, than make a DataSource from the file in Visual Studio when using your Xaml and let Visual Studio write the XPath.

Data Conversion While Binding

If you bind using XML the characters 'Red' to the property 'Background' of a button, the button will be of the color red. This is because the XAML engine will convert the characters 'Red' to a .Net Brush object internally. When using coded APL, the conversion from a character to a .Net Brush will need to be made on the APL side (ex.: ⎕NEW SolidColorBrush (Colors.Red)). Here is some examples of properties and the characters that they are expecting while binding with XML:

Property

Characters

Comments

Color

Literal (like 'Red') or Hexadecimal (like #FFFF0000)

See here for the list of permitted literal color

DateTime

DateTime formatted as format 'G'

(⎕NEW DateTime ⎕TS).ToString(⊂,'G')

Boolean

'True', 'False' or 'Indeterminate'

Visibility

'Visible', 'Hidden' or 'Collapsed'

Number

Number as characters only

for .Net Double use StringToDoubleConverter

For the controls that are expecting a .Net object (like a Double, DateTime or Image) and are not compatible with characters as input values a converter on the .Net side will be required.

Converters

As we can see while binding using XML, it is always characters that are passed as an argument. There is no numbers, only the character representation of those numbers. The DateTime .Net object is represented as ⎕TS formatted as characters with format 'G' (for ⎕TS equal to (2015 3 30 16 40 10) the character representation in format 'G' will be '03/30/2015 16:40:10'). Also sometimes the characters expected for binding are not what the APLer would like to use. For example the APLer is expecting a 1 or 0 as value for a Boolean but the XML binding is expecting the characters 'True' and 'False' instead. It could be also that the control that is receiving the character representation of numbers will not work because it was expecting real numbers. Those situations are corrected with the use of Converters. A Converter can be used on the APL side or on the .Net side. When used on the APL side it is a DFN function that will convert for example the characters 'True' for numeric 1 and the characters 'False' for numeric 0 and vice versa. When used on the .Net side it will be declared in the Xaml and will required a special dll with the converters functions written in a language like C#. However Syncfusion has many controls that will accept characters as input value and will show a formatted output without the use of a converter: DoubleTextBox, PercentTextBox, IntegerTextBox, CurrencyTextBox, MaskedTextBox, DateTimeEdit, CalendarEdit.

Converters .Net Side

Included in the attached zip file is the file named XmlConverters.dll that contains the following basic converters required when binding with Xml:

Name

APL <--> .Net

BooleanConverter

1 0 ¯1 <--> 'True' 'False' 'Indeterminate'

ReverseBooleanConverter

1 0 ¯1 <--> 'False' 'True' 'Indeterminate'

VisibilityConverter

1 0 ¯1 <--> 'Visible' 'Hidden' 'Collapsed'

StringToDoubleConverter

number <--> .Net Double

StringToDateConverter

characters of a DateTime <--> .Net DateTime

OADateToDateConverter

OADate <--> .Net DateTime

Base64ImageConverter

Base64 characters of an image file --> .Net Image

UniversalValueConverter

see here for explanation

The dll XmlConverters.dll needs to be in the same directory as dyalog.exe. The declarations in the Xaml shall be like this (only the converter(s) used need to be declared):

<Window
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:xmlCvt="clr-namespace:XmlConverters;assembly=XmlConverters">
   <Window.Resources>
      <xmlCvt:BooleanConverter        x:Key="bCvt"/>
      <xmlCvt:ReverseBooleanConverter x:Key="rbCvt"/>
      <xmlCvt:VisibilityConverter     x:Key="vCvt"/>
      <xmlCvt:Base64ImageConverter    x:Key="b642iCvt"/>
      <xmlCvt:OADateToDateConverter   x:Key="oadt2dtCvt"/>
      <xmlCvt:StringToDateConverter   x:Key="s2dtCvt"/>
      <xmlCvt:StringToDoubleConverter x:Key="s2dCvt"/>
      <xmlCvt:UniversalValueConverter x:Key="uvCvt"/>
   </Window.Resources>
</Window>

The function demo4 can be used to experiment with XmlConverters.dll

Converters APL Side

A converter on the APL side will be easier to use for the APLer. A typical DFN function for a Boolean converter will look like this:

 _b←{               ⍝ Boolean Converter
     ⍵≡1:'True'     ⍝  1 = 'True'
     ⍵≡0:'False'    ⍝  0 = 'False'
     ⍵≡¯1:''        ⍝ ¯1 = 'Indeterminate'
     ⍵≡'True':1     ⍝ 'True'  =  1
     ⍵≡'False':0    ⍝ 'False' =  0
     ⍵≡'':¯1        ⍝  Empty  = ¯1
     ' '=↑1↑0⍴⍵:0   ⍝ Any character = 0
     'False'        ⍝ Any number = 'False'
 }

The function AplToXml and XmlToApl will used automatically the converter if the name of the property of the namespace is terminating by the name of the converter. It cannot be used if there is no name. For example for the Boolean converter ('_b'):

      ns ← ⎕NS''
      ns.check1_IsChecked_b ← 1
      ns.check2_IsChecked_b ← 0

      {⎕XML ⎕XML ⍵.OuterXml} AplToXml ns
<Data Type="namespace" xmlns="">
  <check1_IsChecked_b Rank="0" Shape="0" Type="array" xmlns="">
    <b>True</b>                  ⍝ The name of the element 'b' is the name of the converter.
  </check1_IsChecked_b>
  <check2_IsChecked_b Rank="0" Shape="0" Type="array" xmlns="">
    <b>False</b>
  </check2_IsChecked_b>
</Data>

The numeric 1 and 0 are converted to the characters 'True' and 'False' and vice versa for a two way binding. Here is the list of APL converters included in the attached namespace:

Type

Name

APL <--> .Net

Boolean

_b

1 0 ¯1 <--> 'True' 'False' 'Indeterminate'

Visibility

_v

1 0 ¯1 <--> 'Visible' 'Hidden' 'Collapsed'

Color

_c

numeric (R,G,B) or (256⊥R,G,B) <--> Hexadecimal Color in characters

DateTime

_d

numeric OADate <--> DateTime in format 'G' in characters

DateTime

_D

numeric ⎕TS <--> DateTime in format 'G' in characters

The function demo5 is a complete example of XML Binding with the basics controls of WPF while using the converters on the APL side. Here is a look at this function when executed:
demo5.png

Installation

  1. Download the file wpfXmlBindindDemo.1.0.zip. It contains the scripted namespace wpfXmlBindingDemo.txt and a dll named XmlConverters.dll

  2. Do a Select all (Ctrl+A) and a copy (Ctrl+C) of wpfXmlBindingDemo.txt.

  3. In your workspace execute )ed ⍟ wpfXmlBindingDemo 

  4. Paste (Ctrl+V) the text into the Dyalog editor
  5. Press Escape and ')save' your workspace
  6. Copy the file XmlConverters.dll to the same directory as your dyalog.exe file (as shown by +2 ⎕NQ'.' 'GetEnvironment' 'Dyalog'). You may need administrator privileges for copying the file.

Version Information

Original author:

Pierre Gilbert

Responsible:

PierreGilbert

Email:

<apgil AT SPAMFREE videotron DOT ca>

CategoryDyalogWpfUtilities