WP.Dialog is (I think) just the 'Form' part of that - just like Android.Dialog and MonoTouch.Dialog - although later it might grow in scope to the entire project - baby steps first:)
Also to be clear... I think WP.Dialog can exist and run without any dependency on MvvmCross - I don't see why it couldn't be useful for code-behind projects, for MvvmLight, etc
The projects
There are 5 projects:
- Core.Dialog - a PCL containing:
- Descriptions - the structs which describe a UI
- Elements - the basic interfaces which UI components have to obey
- Builder - the abstract code which turns Descriptions into Elements
- Android
- Android.Dialog - an Android Library containing:
- Attributes - not currently used but provide a *very* nice way to turn C# models into UIs - see MonoTouch.Dialog for more
- Builder - inherits from Core.Dialog.Builder - provides the *very small* Android specific building part
- Elements - the default elements... the ones to start with are:
- RootElement (which is a mess because it is a RootElement and also has RadioGroup functionality built in)
- StringElement - displays a Caption and a Value
- ValueElement
- displays a Caption and an Editable Value - EntryElement
- FloatElement
- CheckboxElement
- DO NOT START with RadioElement, WebElement, HtmlElement, etc - it's confusing!
- Enums - mainly ignored... most seem to be there for MT.Dialog API compatability
- Root-Level classes - DialogListView and DialogAdapter - together these 2 things provide the 'UI Control'
- DialogSampleApp - the Android Demo project
- MainDialogActivity - is the only activity that has been updated to the new JSON
- Touch - ****nowhere near working****
- Cirrious.MvvmCross.Dialog.
Touch - my branch of MonoTouch.Dialog - Sample - the MonoTouch Sample
Within this layout... I guess WP should work in a new folder WindowsPhone and have two projects - a Dialog and a Sample :)
Naming: I'd like to put these projects in some namespace - for Mvx I used Cirrious (which is my company name) but that's mainly because of the way the project started - it was a company job! No idea what namespace to use, but I'd like to use Something.Dialog.Core rather than just Dialog.Core...
The MainDialogActivity code
For understanding Android.Dialog:
- a good place to start might be MainDialogActivity.
- This contains:
- a big block of JSON
- some code at the start of OnCreate to load the JSON
- a big block of commented out C# which is equivalent to the JSON
A quick walkthrough the code at the start of OnCreate:
DroidResources.Breaking this down:Initialise(typeof(Resource.Lay out)); var parser = new D roidElementBuilder(); var setter = new E xampleActionPropertySetter(); setter.Actions[" ShowDialogActivity"] = ( sender, args) => StartNew(); setter.Actions[" ShowDialogListViewActivity"] = (sender, args) => ClickList() ; setter.Actions[" ElementTest"] = (sender, args) => ClickElementTest(); parser. CustomPropertySetters["Action" ] = setter; var description = Newtonsoft.Json.JsonConvert. DeserializeObject<ElementDescr iption>(JsonText); Root = parser. Build(description) as RootElem ent;
DroidResources.Initialise(typeof(Resource.Lay out));
The first line initialise the DroidResources - what this does is it tells the DroidResources where to look for numeric Android ResourceIds - e.g. when you load a StringElement then the framework might look for some AXML called dialog_string_layout (or similar) - these resources are in the resources folder.
var parser = new DThis creates a builder (not a parser - sorry!).roidElementBuilder();
The Builder stores a lookup list of string names to Element Types
There is a default parameter to DroidElementBuilder which tells the Builder to reflect the Android.Dialog namespace and to look for the default set of Element Types.
Users can also register custom Element Types if they want to - so if you invent a RuneElement, then you can add it.
var setter = new ExampleActionPropertySetter(); setter.Actions[" ShowDialogActivity"] = ( sender, args) => StartNew(); setter.Actions[" ShowDialogListViewActivity"] = (sender, args) => ClickList() ; setter.Actions[" ElementTest"] = (sender, args) => ClickElementTest(); parser. CustomPropertySetters["Action" ] = setter;
This block of code sets up a custom property setter for 'Action'. This means that if ever a property is marked in the Json with a value "@Action:foobar" then this property and foobar will be passed to the custom setter.
In a 'coming soon' step I expect to add an MvxBind custom property setter...
var description =Newtonsoft.Json.JsonConvert. DeserializeObject<ElementDescr iption>(JsonText); This uses PCL JSON.Net to deserialize the ElementDescription JSON. Note that the framework is decoupled from JSON - so users could use XML, ProtoBuf, C#, etc instead!
Root = parser.Finally this line passes the description to the builder :)Build(description) as RootElem ent;
How an Android Element is built
If some JSON comes in like:
{ 'Key':'then this maps to an ElementDescription.String', ' Properties':{ ' Caption':'Click for EntryElement Test', ' Click':'@Action:ElementTest' } }
The builder uses this:
- The Key 'String' is mapped to 'StringElement' - so it uses Reflection to call the parameterless constructor of StringElement (or the constructor with default parameters)
- The builder then iterates the Properties
- uses reflection to set the Caption property on the StringElement to 'Click for EntryElement Test'
- notices the '@Action:' prefix - so passes the Click PropertyInfo and 'ElementTest' to the custom property setter
Note that property values can be strings, numerics or booleans - anything else has to go through a special handler (e.g. a string lookup or a JSON serialised object)
Note that there is no real data binding right now - but that will come with '@MvxBind;' :)
Note that later there may be some chances to add platform specific properties - e.g. something like:
'Properties':{ ' Caption':'Click for EntryElement Test', ' Click':'@Action:ElementTest', '@Droid:WarpSpeed':4, '@WindowsPhone:Pinned':false, }
How an entire Dialog is displayed
In Android and in Touch, the Dialog is displayed using a ListView
The reason for this is because it allows UI virtualisation... and also because MonoTouch doesn't really have a StackPanel!
This use of a ListView makes the UI a bit more complicated than is really needed... e.g. for small forms it would actually be a lot easier to not have any cell reuse.
For WindowsPhone, it might be easier to just use a StackPanel with fixed members - but you could use a List if you wanted to....
In Android, the basic approach is:
- the UI View (Activity) is a List (including Groupings)
- the UI View gets help from an Adapter
- the Adapter stores the list of Elements
- when it comes to time to render the UI, then the Adapter's GetView gets called for every visible 'index'
- the Adapter passes the GetView call through to the GetView on the individual Element - this is passed through to GetViewImpl
- currently the GetViewImpl passes everything through eventually to DroidResources - which loads 'axml' for the element.
- calls like UpdateDetailDisplay and UpdateCaptionDisplay are used in the Element to actually fill in values in the Element
Note that because it uses a list, then there is an opportunity for cell reuse. In Mt.Dialog this works quite well. In Android.Dialog I think it's currently broken - but I will fix it.
So for WP.Dialog
I would expect for WP:
- the same JSON will be used
- the JSON will be parsed by JSON.Net
- a WindowsPhoneBuilder will be used
- this WindowsPhoneBuilder will (by default) know about a set of WindowsPhone Elements - which it will construct using reflection
- these Elements will contain some C# and will somehow map to XAML...
- the XAML will be parented either in a StackPanel (inside a ScrollViewer) or inside a ListView
- if you use a ListView it's just a bit more complicated to route the bindings and to reuse controls (it's a standard 'ListItemSelector' type thing)
- it would be really nice if the XAML is very easily styleable - like custom controls are
- maybe just try some JSON with some StringElements - each has a Caption and Value
- then try adding an EntryElement - Caption and Value
- then try adding a CheckboxElement - Caption and Boolean Value
And then (if we're lucky) people can add platform specific styling to those UIs.
No comments:
Post a Comment