Value combiners
EditValueCombiners
Tibet binding (see wiki/Databinding) introduced a new interface into binding - IMvxValueCombiner
- this interface allows multiple binding sources to be combined together within a single target expression. This interface is used in, for example, the MvxFormatValueCombiner
in order to enable binding expressions like:
local:MvxBind="Text Format('{0} {1} {2}', Greeting(Gender), FirstName, LastName)"
The rules and mechanisms for registering ValueCombiners are similar to those for registering ValueConverters. However, because combiners are not commonly declared in user code, MvvmCross doesn’t currently perform a Reflection sweep across your Core or UI assemblies. If you do want to add by default, then a ValueCombiner class named FooValueCombiner
will be registered under the name Foo
.
Please be aware that withing the MvvmCross Tibet binding syntax, ValueCombiners and ValueConverters share the same ‘registered name’ space - because both of them are expressed as ‘functions’ then it’s impossible to have both a Foo
ValueConverter and a Foo
ValueCombiner - if both are registered then the ValueConverter will always be used rather than the ValueCombiner.
The API for IMvxValueCombiner
is significantly more complicated than IMvxValueConverter
at present and it’s tied to ImvxSubStep - which is part of the internal structure of the MvvmCross binding evaluation engine.
public interface IMvxValueCombiner
{
Type SourceType(IEnumerable<IMvxSourceStep> steps);
void SetValue(IEnumerable<IMvxSourceStep> steps, object value);
bool TryGetValue(IEnumerable<IMvxSourceStep> steps, out object value);
IEnumerable<Type> SubStepTargetTypes(IEnumerable<IMvxSourceStep> subSteps, Type overallTargetType);
}
To assist with authoring ValueCombiners, a number of helper classes are available including the base MvxValueCombiner
class which provides default implementations for all methods in the interface.
An example ValueCombiner which counts the number of non-null inputs bound to it might be:
public class CountingValueCombiner
: MvxValueCombiner
{
public override Type SourceType (IEnumerable<IMvxSourceStep> steps)
{
return typeof(int);
}
public override System.Boolean TryGetValue (IEnumerable<IMvxSourceStep> steps, out Object value)
{
var count = 0;
foreach (var input in steps)
{
object innerResult;
if (!input.TryGetValue (out innerResult))
{
// one of our input bindings is missing so we can't work out our answer
value = null;
return false;
}
if (innerResult != null)
count++;
}
value = count;
return true;
}
}
This could be used in a binding to count (for example) how many peoples have been picked for a band:
local:MvxBind="Text Counting(Guitarist, Drummer, Bass, Vocalist)"
Note that it’s unusual for a ValueCombiner to meaningfully implement SetValue
- this is because it’s unusual (but not unheard of) for multi-bindings to support updating of the multiple source elements from changes in the View.
Developers are very welcome to write their own ValueCombiners if they wish to - please do - but please also be aware that it’s likely that this internal IMvxValueCombiner
API will change in future MvvmCross revisions - we are looking at ways to either simplify this Tibet binding interface and/or ways to make the binding structure more Type-aware so that conversions can be performed at more places within the binding engine. (Developers are also very welcome to suggest improvements for this API!)
To manually register additional value combiners, you can do this in your Setup
class using an override of the FillValueCombiners
method - e.g.
protected override void FillValueCombiners(IMvxValueCombinerRegistry registry)
{
base.FillValueCombiners(registry);
registry.AddOrOverwrite("CustomCombiner", new MyCustomValueCombiner(42));
registry.AddOrOverwrite("CustomCombiner2", new MvxCustomCombiner2ValueCombiner("Summer"));
}
Available ValueCombiners
The ‘standard’ ValueCombiners available in MvvmCross are:
-
If
- used for if-else conditional display with syntaxIf(boolean-test, value-if-true, value-if-false)
For example:
If(HasProAccount, ExtendedName, PromotionalMessage)
-
Format
- used for displaying strings using the standard C# CLRstring.Format
syntax.Format(format-string, input-arguments...)
For example:
Format("{0:ddMMMyyyy} - {1} - {2:0.000}", Entry.Date, Entry.Location, Entry.Reading)
-
And
andOr
- used for logical combinations. Also available as operators -&&
and||
And(test-one, test-two, ...) test-one && test-two Or(test-one, test-two, ...) test-one || test-two
For example:
And(HasProAccount, HasCreditCardDetails) HasProAccount && HasCreditCardDetails
-
Add - used for concatenation or addition - works with
string
,int
,double
Types (other input types may be accepted, but will be converted to one of these types). Also available as the+
operatorAdd(item-one, item-two, ...) item-one + item-two
For example:
Add(SubTotal, Tax) FirstName + ' ' + LastName
-
To be continued… Subtract, Multiply, Divide, Modulus, etc
-
To be continued… GreaterThan, EqualTo, LessThan, GreaterThanOrEqualTo, LessThanOrEqualTo etc
-
To be continued… RGB from the Color plugin