Changes
/* Context Switching */ wrote full section with examples
[[Category:XAML|XAML Best practices]]
=== Contexts and Context Switching ===In xaml, every element in the UI is informed by a '''context'''. This is the data that is delivered by UBIK immediately when binding. Knowing the context that will be used by a content control is vital when using templates, as this directly affects what bindings you can prepare in your template. Furthermore, all content views that use the same template must have the same context, to a degree.
For example:
Two of the more frequently customized elements are Objects and their Metaproperties. A template used for an object will have bindings such as Title, Values[PROPERTY], etc, whereas one designed for a Metaproperty will have Description, DisplayValue, Unit, and so on. Using a template design for an object will have no benefit if the context is that of a property, and vice versa.
==== Where does the context come from? ====
Context is inherited. When you begin customizing a xaml template, it generally has a known use, such as a child area, document viewer, or item in a property list, to name just a few of many. In these cases, the context is quite clear. However, when you begin creating templates that can be used anywhere on a page, then there will likely be the need to define what context should be applied to each specific instance of the template in use. Returning to the example shown in the previous section, we see 3 headers each with 3 uses of the same template, a [[Property_Based_Content_Filters|property-based content filter]]. In each case, the context needs to be set to a specific metaproperty, that will then be used to inform all the displays and interactivities added to the template.
==== Context Switching ====
To reiterate, context is almost always inherited. If you forget to assign a specific context to a content control, the context of the xaml element that hosts that content control will be used. Context-switching is simply the name given to the act of assigning a different context.
It is also usually very simple to do:
'''UWP'''
<source lang = "xml">
DataContext="{Binding ...}"
</source>
'''Xamarin'''
<source lang = "xml">
BindingContext="{Binding ...}"
</source>
The above attributes can be added to any control to change it's binding context.
Try this experiment:
<source lang = "xml">
<TextBlock
DataContext="{Binding ParentLevel}"
Text="{Binding Title}" />
</source>
By using this code snippet, we expect to see the Title or the current object. However, because we have a context switch applied, we would instead see the Title of the parent object.
{{Attention| For Xamarin use '''Label''' instead of TextBlock and '''BindingContext''' instead of DataContext.}}
==== ⚠️ Important Note ====
Using this technique to switch the context of a control does it for '''all bindings on that control'''. Since the entire control is now 'focused' directly on the parent object related to the current context, all other bindings on that control, for example Visibility, will need to be adapted. Furthermore, since context is inherited any controls contained within the context-switched one (imagine it's a grid with children controls) will all also have the context of ParentLevel.
==== ⚠️ Context Switching And Templates ====
As described in the previous section, DataTemplates are designed to be used as templates for data contexts, therefore the content control used to render them, controls:ContentControl, has the TemplateContext property which allows you to set the binding context '''for the template'''. The important difference to note is that the controls:ContentControl itself will not use the TemplateContext, but rather the inherited context from its hosting xaml.
Because they are independent of each other, it allows more sophisticated usage of binding contexts, for example, when ''Object A'' has ''Status B'', show ''Property C''.
<source lang = "xml">
Xamarin:
<controls:ContentControl (displayed on child area of Object A)
IsVisible="{Binding Values[STATUS], Converter={StaticResource EqualityToBool}, ConverterParameter=B}"
TemplateContext="{Binding PropertyItems[PROPERTYC]}"
ContentTemplate="{StaticResource MyPropertyTemplate}" />
</source>
On the other hand, since the ControlTemplate is not designed to be used this way, it has no inherent binding context attribute that can be assigned to it's content only. To use it this way would therefore require a context switch on the ContentView used to render it, with the related adjustments required to bindings placed on the ContentView itself;
<source lang = "xml">
Xamarin:
<ContentView (displayed on child area of Object A)
BindingContext="{Binding PropertyItems[PROPERTYC]}"
IsVisible="{Binding CallingViewModel.Values[STATUS], Converter={StaticResource EqualityToBool}, ConverterParameter=B}"
ControlTemplate="{StaticResource MyOtherPropertyTemplate}" />
</source>
{{Hint|CallingViewModel (as used on the IsVisible attribute) can be added to a metaproperty's binding path to bind to its context object.}}
{{Attention|Remember that Styling in Xaml is type-based, so you cannot use the same template with controls:ContentControl (ContentTemplate attribute) and ContentView (ControlTemplate attribute), as DataTemplate and ControlTemplate are technically different types.}}
<br>
<br>
<br>
{{UnderConstructionEnd}}