= wpfXmlBindingDemo = ~-<>-~ <> `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 at [[wpfXamlDemo||]]. Either way the UI needs to be populated with the data and again this can be done either directly within the APL code or with !DataBinding. With APL code each element of the UI controls that display 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 variable directly with multiple controls of the UI. If the !DataBinding is made bidirectional then changes in the UI are immediately reflected by the associated APL variable. When using just APL code the data will need to be retrieved from each control and saved back to the APL variable. For binding you can use the I-Beam 2015 (`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 resides on the .Net side of the fence. Some utility functions for dealing with .Net !DataTables are available at [[netDataTable||]]. Refer to the Dyalog tutorials on how to use the `2015⌶` I-Beam. For large tabular data, binding with a !DataTable will be faster than binding with XML. When there is a multitude of single controls to bind from the same APL variable XML is the better choice. This page will demonstrate the use of a .Net !XmlDocument representing the APL data for binding with WPF controls. === XML Representation of APL Data === The XML representation of the data needs to be made in such a way that the XPath used in the Binding will be able to find the data but also it needs to contain all the information to revert the !XmlDocument back to APL data when used with two-way binding. The functions `AplToXml` and `XmlToApl` in the attached namespace are doing just that for simple APL data that is not nested. Here are some examples: ==== Vector: ==== {{{ ⍝ Example for a vector {⎕XML ⎕XML ⍵.OuterXml} AplToXml 1 2 (⍳0) ('') 'some text' ⍝ 'Data' is the name of the root element by default. 1 2 ⍝ The Rank(⍴⍴), Shape(⍴) and the Type(array or namespace) are attributes in the root element ⍝ The name of the elements with the data is either (for number) or (for string) ⍝ The 'Elements' of the Xml are holding the data. some text ⍝ Empty values are permitted and used for place holder. Use ⍳0 for numbers and '' for characters. }}} 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 ⍝ This is the 'Attribute' style representation of the matrix ⍝ The name of the elements are still 'n' for numbers and 's' for characters ⍝ The column names are 'C1', 'C2' etc. by default ⍝ The 'Attributes' of the Xml are holding the data. Elements are empty ⍝ The equivalent 'Element' style representation is shown below for information only: 1 2 three 4 five 6 }}} 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 Marco Polo Venezia Travelling }}} Each property name of the namespace will hold 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; more information is provided 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' ns.Books.ID ← 100 101 103 {⎕XML ⎕XML ⍵.OuterXml} AplToXml ns }}} Each property of the namespace `Books` must have the same number of items. This is typical for binding data that will be presented in a tabular form like a !DataGrid or a !ListView where each column will have a selected name (this will allow a converter on the APL side to function as well). A typical binding would be: '''"{Binding XPath=/Data/Books/@Author}"'''. The function `demo2` in the attached namespace is a comprehensive example for this type of binding. The functions `AplToXml` and `XmlToApl` are used for two-way binding. The functions has to figure out the data type (numeric or character) of each value. The function `MatToXml` can be used for one-way binding of an APL matrix without checking if each item is 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 the data back to APL. See the function `demo3` for an example. ==== About XPath ==== If you are not sure of the syntax for [[https://www.wikiwand.com/en/XPath|XPath]] you can use the function `XmlDocToFile` included in the attached namespace to write the !XmlDocument to disk, then create a !DataSource from the file in Visual Studio 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. Usually you can use the same characters that are used to define a property in XAML for binding in XML (the XAML engine will try to do the conversion). When coding in 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 are 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 the [[https://msdn.microsoft.com/en-us/library/system.windows.media.brushes%28v=vs.110%29.aspx|MSDN|]] 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 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 are 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 an APLer would like to use. For example, an APLer is expecting a 1 or 0 as value for a Boolean but the XML binding is expecting the characters 'True' and 'False' instead. A control receiving the character representation of numbers may also refuse to cooperate because it was expecting real numbers. This problem can be solved by using Converters. A Converter can be used either on the APL side or on the .Net side. When used on the APL side it is a function that will convert for example the text vector 'True' to numeric 1 and the text vectors 'False' to numeric 0 and vice versa. When used on the .Net side it will be declared in the Xaml and will require a special DLL with the converters functions written in a language like C#. Syncfusion has many controls that will accept characters as input value and will show a formatted output without the use of a converter: * [[http://help.syncfusion.com/wpf/doubletextbox/getting-started|DoubleTextBox|]], * [[http://help.syncfusion.com/wpf/percenttextbox/getting-started|PercentTextBox|]], * [[http://help.syncfusion.com/wpf/integertextbox/getting-started|IntegerTextBox|]], * [[http://help.syncfusion.com/wpf/currencytextbox/getting-started|CurrencyTextBox|]], * [[http://help.syncfusion.com/wpf/sfmaskededit/getting-started|MaskedTextBox|]], * [[http://help.syncfusion.com/wpf/datetimeedit/getting-started|DateTimeEdit|]], * [[http://help.syncfusion.com/wpf/calenderedit/getting-started|CalendarEdit|]], * [[http://help.syncfusion.com/wpf/timespanedit/getting-started|TimeSpanEdit|]], === Converters .Net Side === Included in the attached zip file is a file named `XmlConverters.dll` which contains the following basic converters useful when binding with XML: || '''Name''' || '''APL ↔ .Net''' || || !BooleanConverter || 1 0 ¯1 ↔ 'True' | 'False' | '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 || 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) and `⎕USING` does not need to be define because it is in the same directory as dyalog.exe: {{{ }}} The function `demo4` can be used to experiment with `XmlConverters.dll`. There are also many converters included in the assemblies of Syncfusion that can be used. === Converters APL Side === A converter on the APL side will be easier to use for an APLer. A typical direct 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 use 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 (only when there is a namespace). For example for the Boolean converter ('_b'): {{{ ns ← ⎕NS'' ns.check1_IsChecked_b ← 1 ns.check2_IsChecked_b ← 0 {⎕XML ⎕XML ⍵.OuterXml} AplToXml ns True ⍝ The name of the element 'b' is the name of the converter. False }}} The numeric 1 and 0 are converted to the text vectors '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 [[https://msdn.microsoft.com/en-us/library/system.datetime.tooadate%28v=vs.110%29.aspx|OADate|]] ↔ !DateTime in format 'G' in characters || || !DateTime || _D || numeric ⎕TS ↔ !DateTime in format 'G' in characters || The function `demo5` is a fully-fledged example of XML Binding with WPF's basics controls while using the converters on the APL side. Here is a screenshot taken after executing the function: {{attachment:demo5.png || width=675}} == Installation == 1. Download the file [[attachment:wpfXmlBindingDemo.1.1.zip]]. It contains the scripted namespace `wpfXmlBindingDemo.txt` and a DLL named `XmlConverters.dll` 1. Do a "Select all" (Ctrl+A) and a "Copy" (Ctrl+C) of `wpfXmlBindingDemo.txt`. 1. In your workspace execute `)ed ⍟ wpfXmlBindingDemo`. 1. Paste (Ctrl+V) the text into the Dyalog editor. 1. Press Escape and ')save' your workspace. 1. Copy the file `XmlConverters.dll` into the Dyalog installation directory as shown by `+2 ⎕NQ'.' 'GetEnvironment' 'Dyalog'`. You may need administrator privileges for this. Optionally to de-script the namespace you can do: {{{ #.wpfXmlBindingDemo←{('n' ⎕NS ⍵)⊢n←⎕NS ''}#.wpfXmlBindingDemo }}} == Version Information == ||Original author: ||Pierre Gilbert || ||Responsible: ||PierreGilbert || ||Email: || <> || ---- CategoryDyalog - CategoryDyalogDotNet - CategoryDyalogWpfUtilities - CategoryDotNet