Binding

13 views
Skip to first unread message

tylerl

unread,
Jul 23, 2010, 2:45:51 PM7/23/10
to Spark View Engine Dev
Robert, would you mind posting the core details of the "binding"
feature you demo'ed yesterday? I think this a "killer feature" that is
going to make spark indispensable going forward.

Louis DeJardin

unread,
Jul 23, 2010, 9:29:04 PM7/23/10
to spar...@googlegroups.com
Added some rough documentation...

http://sparkviewengine.com/documentation/bindings

--
You received this message because you are subscribed to the Google Groups "Spark View Engine Dev" group.
To post to this group, send email to spar...@googlegroups.com.
To unsubscribe from this group, send email to spark-dev+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/spark-dev?hl=en.


Igor Loginov (aka ilog2000)

unread,
Jul 25, 2010, 4:54:00 PM7/25/10
to Spark View Engine Dev
Louis, can I ask you to elaborate on that a little bit more? The
documentation answers "how to" question. But questions "why, what for"
are not so clear to me. At a glance, macros and "underscored" partials
do practically the same job. The only funny thing I see now is the
possibility to convert all pieces of code in view into markup analogs.
Could you, please, provide practical scenarios / use cases for
binding ? Thank you !

Rob G

unread,
Jul 26, 2010, 3:31:36 AM7/26/10
to spar...@googlegroups.com
I'll be putting blog post about my experiences with Bindings so far out later this week. Hopefully that will go some way towards helping to position it for you.

Will post the link here when it's up

Regards,
Rob

Igor Loginov (aka ilog2000)

unread,
Jul 26, 2010, 5:17:24 AM7/26/10
to Spark View Engine Dev
Rob, thank you, it would be great. Actually, I have already asked you
for materials from MVCConf in your blog. If possible, please, give
a;so a big picture of this feature, maybe some problems - solutions.
> > spark-dev+...@googlegroups.com<spark-dev%2Bunsubscribe@googlegroups .com>
> > .
> > > For more options, visit this group athttp://
> > groups.google.com/group/spark-dev?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Spark View Engine Dev" group.
> > To post to this group, send email to spar...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > spark-dev+...@googlegroups.com<spark-dev%2Bunsubscribe@googlegroups .com>
> > .

Louis DeJardin

unread,
Jul 26, 2010, 1:15:00 PM7/26/10
to spar...@googlegroups.com
That's true, it is a bare-bones reference, but everything else in the documentation is also. The problem with mixing "why" in with your docs is they end up turning into a set of articles about web development... Reduces the information density and focus of the docs...

Like Rob said, blog posts help fill that gap. The other question - contrasting macro vs partial vs binding - would also be a great topic of a post.

To unsubscribe from this group, send email to spark-dev+...@googlegroups.com.

Igor Loginov (aka ilog2000)

unread,
Jul 26, 2010, 2:25:40 PM7/26/10
to Spark View Engine Dev
Louis, thank you for the comments. A couple of questions along reading
the doc page:
1. 'child::*' - it looks a little bit ... unusual. Maybe better to
reserve two attributes like "innerText" & "innerHtml" ?
2. Dictionary&lt;string,object&gt; - is this XML escaping? Can we use
[[ ]] like for Model ?

As for the rest - waiting for Rob's post (and trying this on by
myself)...

tylerl

unread,
Jul 26, 2010, 3:37:11 PM7/26/10
to Spark View Engine Dev
The "whys" and "what fors" are pretty obvious once you see some clear
examples. Lou's last example, which modifies the "<form>" tag to
actually insert a "# using (Html.BeginForm())..." into the code I
think is a compelling usage case.

In essence, bindings allow you to create your own tags (or overload
existing ones), which when used, do pretty much anything you want them
to. With the right set of bindings, you don't have to include any real
"code" in your templates at all, which is a great help when dealing
with third-party designers.

I do agree with the general murmur of dissent about a few of the
syntax details, though. I do like with the general idea of the xpath-
like references. But some bits look... i don't know... messy.

Louis DeJardin

unread,
Jul 26, 2010, 3:37:31 PM7/26/10
to spar...@googlegroups.com
2. Done...

It's xml escaping - the bindings file is parsed as a normal xdocument. The information is needed before spark parses a template, which is why the bindings file itself isn't a .spark file.

But there are a small number of grammer rules used to locate the terms in the replacement text. I added [[ and ]] to < and > replacement in those rules.


1. Just that, or with an at like @innerText, @innerHtml?

The @attr is in the spirit of using an xpath-like syntax for bindings... So that's where the child::* came from - it's an xpath axes - http://www.w3schools.com/xpath/xpath_axes.asp

Thing with text/html is it's not always html output, and innerText in the dom carries the sense you're stripping markup... Plus the code isn't text or html, really.

@innerText
@innerHtml
@innerContent
@childContent
@child
@content
@inner

Problem is the nicer (shorter) ones are most likely to conflict with an attribute name someone would want to use... Maybe something that doesn't use the @ at all?

[child]
[inner]
:child

Or something that's entirely punctuation?

@**
@@*
@.
@:
@+

Maybe it's because I've been exposed to it and xpath before... I still lean towards 'child::*' as fairly clear...

Igor Loginov (aka ilog2000)

unread,
Jul 26, 2010, 4:59:49 PM7/26/10
to Spark View Engine Dev
Ups! Sorry, I did not associate the syntax with XPath... I offered
innerText/innerHtml just because I decided that child content is
always evaluated as a text and it can be exposed as a standard
parameter automatically and everywhere in bindings. I didn't think
about nested code or binding sub-elements. I see now that I have too
little details... Basically, no real problem with child::* - it was
simply looking so non-HTML :)

And thank you guys - I see the purpose of this feature much better
now.

On Jul 26, 9:37 pm, Louis DeJardin <lodej...@microsoft.com> wrote:
> 2. Done...
>
> It's xml escaping - the bindings file is parsed as a normal xdocument. The information is needed before spark parses a template, which is why the bindings file itself isn't a .spark file.
>
> But there are a small number of grammer rules used to locate the terms in the replacement text. I added [[ and ]] to < and > replacement in those rules.
>
> 1. Just that, or with an at like @innerText, @innerHtml?
>
> The @attr is in the spirit of using an xpath-like syntax for bindings... So that's where the child::* came from - it's an xpath axes -http://www.w3schools.com/xpath/xpath_axes.asp

Louis DeJardin

unread,
Jul 26, 2010, 6:09:11 PM7/26/10
to spar...@googlegroups.com
Well, like tylerl, mentioned it does have a strange first impression. If there's a nice alternative it would be good to hear it...

Igor Loginov (aka ilog2000)

unread,
Jul 26, 2010, 6:34:26 PM7/26/10
to Spark View Engine Dev
I was re-thinking the idea of innerText / innerHtml and seems, it
might be possible. Of course, I don't know details, so this can be
just a mental exercise.

We have some custom tags, some of them come from "underscored"
partials, some from bindings. These custom tags have inner (child)
content. We add to classes responsible for their rendering properties
InnerText and InnerHtml. When processing partials, we just assign the
content with or without Html encoding. In the case of binding we
firstly check if binding element contains <start>...</
start>...<end>...</end> tags. If so, InnerText = String.Empty;
InnerHtml = String.Empty; Otherwise, we assign them. Now these
properties can be exposed as standard for custom tags attributes. Even
not exposing the properties to a programmer, the inner content can be
used, for example, in error processing (default text to be rendered if
something happened).

Can it be real ?

On Jul 26, 10:59 pm, "Igor Loginov (aka ilog2000)"

davethieben

unread,
Aug 1, 2010, 11:28:06 AM8/1/10
to Spark View Engine Dev
I was wondering if Robert or Louis could post the Bindings.xml Robert
used in his MVCConf presentation that has a lot of the HTML helpers
already in it?

Also, I'm wondering if it is possible (or could be) to have multiple
bindings files? I can foresee having a standard set (like the one
used in the presentation) named something like "Mvc.Bindings.xml" and
then having custom rules for a project like "MyClient.Bindings.xml",
"MyStandards.Bindings.xml", etc.

thanks guys, great work.

Rob G

unread,
Aug 1, 2010, 5:44:10 PM8/1/10
to spar...@googlegroups.com
Hi there,

Last week I posted the link to the samples source code download on my blog as an update:


Regards,
Rob

James R

unread,
Aug 2, 2010, 7:55:41 AM8/2/10
to Spark View Engine Dev
@davethieben I'm also wondering if it is possible to have multiple
binding files. Seems you want static binding files, however I'm
excited more about the possibility of dynamic binding files that are
bound depending on context such as the current theme.

Having what you want should be straightforward, just

public void RegisterViewEngine(ICollection<IViewEngine>
engines)
{
var container = SparkEngineStarter.CreateContainer();
container.SetServiceBuilder<IBindingProvider>(c => new
ProjectBindingProvider());
SparkEngineStarter.RegisterViewEngine(engines, container);
}

public class ProjectBindingProvider : BindingProvider
{
public override IEnumerable<Binding>
GetBindings(Spark.FileSystem.IViewFolder viewFolder)
{
var defaultBindings = GetCustomBindings(viewFolder,
"Mvc.Bindings.xml");

var projectBindings = GetCustomBindings(viewFolder,
"MyClient.Bindings.xml"); // Config driven?

return projectBindings.Union(defaultBindings, new
BindingComparer()); // Compares based on element name, project will
override any default element bindings.
}
}

public IEnumerable<Binding>
GetCustomBindings(Spark.FileSystem.IViewFolder viewFolder, string
bindingFileName)
{
if (viewFolder.HasView(bindingFileName) == false)
return new Binding[0];

var file = viewFolder.GetViewSource(bindingFileName);
using (var stream = file.OpenViewStream())
{
using (var reader = new StreamReader(stream))
{
return LoadStandardMarkup(reader);
}
}
}

Not tested or anything, but might get you started.

Anyway, I think it would be really cool if the bindings/bindings file
could be bound dynamically depending on the users current theme or
device etc. However currently the View gets compiled/bound once and
used for all subsequent requests. Is there any way to be able to use
different bindings per request depending on some context? Prefer not
to compile the view each request... ;)

Cheers,
James

Louis DeJardin

unread,
Aug 2, 2010, 3:24:13 PM8/2/10
to spar...@googlegroups.com
Yep, that's why the bindings are parsed each time a view is loaded instead of once when the engine is created. There could be lots of ways you could want them to vary.

If you wanted to vary the bindings per view file you could also pass the path along as an argument to the binding provider... Starting around ViewLoader.cs line 147 where it calls FindBinding() you could add a string viewPath argument along down to the IBindingProvider.GetBindings call.

If you had that, and your themes live in different paths, something you could do is look for bindings.xml in each of the folders from the view's location back down to the root. The DefaultBindingProvider.cs implementation is very simplistic.

And yes, I know... DefaultBindingProvider provides the file location strategy and it inherits from BindingProvider which provides the default parsing strategy. "Favor composition over inheritance" - they should be separate classes with an IBindingParser interface between them. My bad. :)

-----Original Message-----
From: spar...@googlegroups.com [mailto:spar...@googlegroups.com] On Behalf Of James R
Sent: Monday, August 02, 2010 4:56 AM
To: Spark View Engine Dev
Subject: Re: Binding

Cheers,
James

--

James R

unread,
Aug 3, 2010, 10:23:21 AM8/3/10
to Spark View Engine Dev
Thanks Louis, I've got it mostly working by combining something
similar to the above with the ThemeDescriptorFilter, so now it won't
cache the view when I want to use the theme bindings :) Some hacks as
ControllerContext isn't passed in to GetBindings that I still need to
resolve.

I'm not sure just passing the viewPath would be enough, as that
wouldn't allow for using a theme binding file on a view file that
hasn't been overridden by the theme e.g. having a Views/MyTheme/
MyThemeBindings.xml bind to Views/Shared/Application.spark. So when a
viewPath of Views/Shared/ comes in it wouldn't know where to get the
theme specific bindings from.

You may be interested, I spent some very interesting time figuring out
why <use master="Html"/> wasn't working in my Application.spark.

Turns out on the latest ,
[ConfigurationProperty("prefix")]
public string Prefix
{
get { return (string)this["prefix"]; }
set { this["prefix"] = value; }
}

Is defaulting to an empty string when a configuration isn't given.
This means in DefaultDescriptorBuilder.Initialize the following line
is passing in "" as the prefix.

_grammar = new UseMasterGrammar(_engine.Settings.Prefix);

Which causes the following line in the constructor of UseMasterGrammar
to set startOfElement to "<:use".

var startOfElement = (_prefix != null) ? Ch("<" + _prefix + ":use"):
Ch("<use");

I've got it working by just doing a !string.IsNullOrEmpty(_prefix)
instead.

Anyway a fun adventure through the codebase, learning a lot even
though I'm new to spark. Very impressed :)

Mike Nichols

unread,
Aug 6, 2010, 8:10:27 PM8/6/10
to Spark View Engine Dev
Just wanted to chime in that bindings are the freakin' bees knees. I
wanted to create a definition list with lambda expressions and the
same convention across the site like so:
<props if="Model.HasOwnerInfo()">
<prop exp="project=>project.OwnerRolePlayerName" term="Name" />
<prop exp="project=>project.OwnerProjectNumber1" />
</props>

This outputs this:
<dl>
<dt><span>Name</span></dt>
<dd>Ruprecht the Monkey Boy
<dt><span>Owner Project Number 1</span></dt>
<dd>Dirty Rotten Scoundrels</dd>
</dl>

And the bindings:

<element name="props">
<start>"&lt;dl class='props'&gt;"</start>
<end>"&lt;/dl&gt;"</end>
</element>
<!--prop : renders a key-value dt-dd pair using a lambda for input--
>
<element name="prop">"&lt;dt&gt;&lt;span&gt;" +
Html.Term('@term',@exp) + "&lt;/span&gt;&lt;/dt&gt;" + "&lt;dd&gt;" +
Html.TryGetModelValue(@exp,null) + "&lt;/dd&gt;"</element>
<element name="prop">"&lt;dt&gt;&lt;span&gt;" + Html.Term(null,@exp)
+ "&lt;/span&gt;&lt;/dt&gt;" + "&lt;dd&gt;" +
Html.TryGetModelValue(@exp,null) + "&lt;/dd&gt;"</element>


Thanks for putting the docs and this feature out there!
Reply all
Reply to author
Forward
0 new messages