* 🏆 '''Only include xamls that are needed for your customizing.'''
** Remove files for child Areas and Items that are not included in the project this customizing will be used for. This is especially relevant when copying customizings from other projects.
<br>
** This is especially an issue in Xamarin, both for performance, but also because sfListViewExt tends to cause layouting issues by taking up more space than needed, unlike in UWP where a ListViewExt is capable of calculating its size based on the size of its items. Therefore, when using nested ListViews in Xamarin, constrain the size of the inner ListView with a fixed HeightRequest attribute (or WidthRequest in the case of a horizontal list).
** 🏆 '''Alternatives to the optimized ListViews should be used with extreme caution.''' Controls such as CollectionView or BindableLayout are not optimized for good performance in UBIK.
<br><br>
** Sometimes it’s unavoidable that multiple containers are needed. In Xamarin, applying the [[Xamarin_XAML#Layout_compression_examples|HeadlessLayout]] style can reduce their impact on the visual tree.
** Some ideas for reducing the number of nested controls can be seen [[XAML_Best_practices#Alternatives_to_using_Multiple_Controls|later in this article]].
<br>
* The localized Style definitions in this StackPanel will be passed down to all controls contained within it, no matter how deep the nesting goes.
* The BasedOn attribute can be used to create a sub-style based on another existing style. However, the TargetType must always match.
<br><br>
=== Simplifying Layouts ===
In UWP / on desktop UBIK, the processor is generally powerful enough to handle more complex UIs. However, mobile devices running Xamarin versions of UBIK will noticeably struggle to render sophisticated UIs made of deeply nested levels of containers. There are two ways this situation can be improved; the first is to reduce the number of containers used, and the second is to apply [[Xamarin_XAML#Layout_compression_examples|Layout Compression]] wherever possible. Finally, some ideas will be presented for other ways to reduce the number of controls needed to render the same UI.
<br>
==== Reducing Containers ====
<FormattedText>
<Span FontFamily="{StaticResource UBIKSymbols}" Text="{x:Static resources:UBIKIcons.IconName}" />
<Span Text="Name " />
<Span Text="Description lorem ipsum..." />
</FormattedText>
</tab>
Note: (without the blank space) is the Xamarin glyph code for a Linebreaknewline. The equivalent in UWP is 
 .
</tabs>
Another thing to consider is how many times this particular UI definition will be rendered on screen. You have more freedom to be uneconomical in your use of controls when when designing items that will appear once on a page, such as the page header, rather than with item templates or control templates that are rendered several, or even dozens, of times in one view.
<br>
==== Layout Compression ====
<br>
==== Alternatives to using Multiple Controls ====
<br><br>
[[Category:Pages with broken file links|XAML Best practices]]
[[Category:XAML|XAML Best practices]]
== Templating ==
=== Template Selectors ===
Various parts of the UBIK UI are dynamically swapped in based on specific conditions. One example is the UBIKPropertyDirectItemContainer.xaml, which serves as the base for an item in the property list, and which renders a different type-appropriate editing UI for each kind of property input (such as textboxTextBox for manual input String, Double, or Integer; selectionfor link properties, or list-based String, Double, or Integer; clock and calendar pickers for DateTime; Lat., datetimeLon., and Alt. input for geo coordinates, etc).
The logical tree used by these selectors to render different UIs is documented in our article [[UBIK_Templates]].
<br><br>
=== DataTemplate vs. ControlTemplate in Xamarin ===
* Example 2: Consider a Property ItemTemplate, where we can view or edit a metaproperty. In this case, the '''context''' of the ItemTemplate would be a single property, and the bindings available would reflect that; we can bind to its Description, Value, DisplayString, Unit, or even its SortedValueRecords, if property change history is activated.
* Use a '''ContentControl''' or our custom '''controls:ContentControl''' (with the attribute ContentTemplate="{DynamicResource ...}" and TemplateContext="{Binding ...}") to display it.
<br>
==== ControlTemplate ====
ControlTemplate is technically used for showing how a specific control can be used; for example, if you want to customize a new template for how a Button should appear. However, it can be used similar to the DataTemplate, with one added bonus; its ContentPresenter sub-control allows for dynamically adding content at every instance, as opposed to a single universal layout that is shared by all.
* Note that implicit styles can also be added to the ControlTemplate, and will be inherited by any content nested in the ContentView.
* Use a '''ContentView''' (with the attribute ControlTemplate="{DynamicResource ...}") to display it.
<br>
{{Attention|Since the ControlTemplate is not technically designed to work directly with data bindings, it does inherit the context from its ContentView by default. However this can be easily fixed by adding the <nowiki>BindingContext="{TemplateBinding BindingContext}"</nowiki> attribute to the root grid of the template.}}
<br>
{{Hint|An understanding of '''Contexts''' is fundamental to using templates, as this informs what data bindings are directly available. Some more information can be found at this article on [[Object_hierarchy_in_XAML:_NextLevel,_ParentLevel,_LinkedLevel#The_ContentViewModel.28s.29|the ContentViewModel]] }}
<br><br>
=== ControlTemplate in UWP ===
The ContentControl is used to render an instance of a template.
<br>
<br>
[[Category:Pages with broken file links|XAML Best practices]]
[[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 contextsimilar contexts, to a degree.
For example:
Two of the more frequently customized elements are Objects and their Metaproperties. A template used for an a UBIK object will have bindings such as Title, Values[PROPERTY], etc, whereas one designed for a Metaproperty will have Description, DisplayValue, Description, Unit, and so on. Using a template design designed for an a UBIK object will have no benefit if the context applied to it 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 general templates that can be used anywhere on a pagein the client, then there will likely be the need to define specify what context should be applied to each specific instance of time the template in useis used. Returning to [[Image:XBP_ContentTemplates.png]] In the above example shown in the previous section, we see 3 headers each with 3 uses a variety of the same property editing fields. To cut down on repetitive XAMLing, a templateis created for inputting a single property, consisting in this case of Description, DisplayValue, a [[Property_Based_Content_Filters|placeholder label, and some indicators such as whether the property-based content filter]]is required or filled. In each case, the context needs to be set to a specific metaproperty, defined on the 'controls:ContentControl' that will then be used to inform all hosts each instance of the displays and interactivities added template, through the TemplateContext attribute. <source lang = "xml"><controls:ContentControl ContentTemplate="{DynamicResource PropertyField_Required}" TemplateContext="{Binding Properties.VisibleItems[MP_DETECTION]}" > <controls:ContentControl.GestureRecognizers> <TapGestureRecognizer Command="{Binding Properties.VisibleItems[MP_DETECTION].PropertyClickedCommand}"/> </controls:ContentControl.GestureRecognizers></controls:ContentControl></source> {{Hint|Adding the behavior to the ContentControl, rather than defining it in the templateitself, allows flexibility in the customizing as different property-editing commands can be paired with the same UI based on the required functionality.}}
==== Context Switching ====
To reiteraterepeat, context is almost always inherited. If you forget to assign a specific context to a content control(as in the above example), the context of the xaml XAML element that hosts that content control will be used. Context-switching is simply the name given to the act When you think about it, any number of assigning a different nested Grids still inherit the contextof the area or item template they are hosted in.
Context-switching is simply the name given to the act of assigning a different context to a particular control, when needed. It is also usually very simple to do:
'''UWP'''
<br>
The above attributes can be added to any control to change it's binding context.
<br><br>
Try this experiment:
Text="{Binding Title}" />
</source>
<br>
<br>
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.}}
<br>
<br>
[[Category:Pages with broken file linksBy 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. For Xamarin use '''Label''' instead of TextBlock and '''BindingContext''' instead of DataContext. {{Attention|XAML Best practices]]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 a different context, existing bindings will need to be adapted. An easy example is the Visibility of the TextBlock, which we might still want to bind to certain conditions on the child object, while displaying the data of the parent. One exception is the controls:ContentControl, which through its TemplateContext attribute accepts the possibility to have a different context for its content, therefore decoupling the context of the template from the actual control, [[Category:XAMLXAML_Best_practices#Context_Switching_And_Templates|XAML Best practicesas described below]].}} Furthermore, since context continues to be inherited, any controls contained within the context-switched one (imagine it's a Grid containing more elements, rather than a simple TextBlock) will all also have the context of ParentLevel.
==== ⚠️ 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 ====
<tabs>
<tab name="DataTemplate (Xamarin only)">
{{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}}
[[Category:Pages with broken file links|XAML Best practices]][[Category:XAML|XAML Best practices]]
== Performance ==
== Testing of UI ==
XAML can be sometimes very weird, there are dependencies or default values that you don’t see immediately. So, a good way to prevent millions of fixes for the customer, because the environment, different device or even a different windows version destroys your UI, is to write a test plan where you test your implementation. It’s important to see exactly your controls in action on their own and acting with each other, so you can prevent doing lots of ‘easy’ fixes.
{{UnderConstructionStart}}
== Improving performance on complex List item templates ==
=== Overview ===
Performance issues in XAML-based UI development often stem from unnecessary UI rendering and binding errors. Hidden elements remain in the UI tree, impacting performance, while premature bindings cause background errors. To optimize complex list item templates, UI content can be loaded only when needed, and binding errors can be reduced by applying view models at the control level. These improvements enhance efficiency, reduce log clutter, and improve maintainability.
=== Technique 1: Loading UI content on demand ===
It was discovered that UI controls hidden with '''IsVisible=False''' remain in the UI tree. To improve performance on highly complex item templates, like UBIKTaskItem, rendered repeatedly such as in ListViews, a workaround can be applied to only load the UI content when the '''visibility''' binding condition is met.
==== Previous Approach ====
Previously, we used '''IsVisible''' directly with a binding condition. The approach looked like this:
<source lang = "xml">
<Label IsVisible="{Binding MROViewModel.PreviousValue, Converter={StaticResource NullToNotBool}}">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding MROViewModel.PreviousValue}" />
<Span Text=" " />
<Span Text="{Binding MROViewModel.Unit}" />
</FormattedString>
</Label.FormattedText>
</Label>
</source>
<br>
==== Improved Approach ====
To prevent unnecessary loading of UI elements when their '''visibility''' is False, it is possible to replace the UI content with a content hosting control, such as a '''ContentView''' or '''ContentControl'''. The original content should instead be defined as a template in '''UBIKThemes''', as shown below.
<source lang = "xml">
<ContentView>
<ContentView.Triggers>
<DataTrigger Binding="{Binding MROViewModel.PreviousValue, Converter={StaticResource NullToNotBool}, TargetNullValue=false, FallbackValue=false}"
Value="True" TargetType="ContentView">
<Setter Property="ControlTemplate" Value="{StaticResource PreviousValueTemplate}" />
</DataTrigger>
</ContentView.Triggers>
</ContentView>
</source>
<br>
The important part of the snippet above is the '''DataTrigger'''. Through this technique, the '''ControlTemplate''' of the content hosting control is only set once the visibility condition is met, preventing the UI content from being loaded until it is explicitly required.
And the associated '''ControlTemplate''', located in UBIKThemes:
<br>
<source lang = "xml">
<ControlTemplate x:Key="PreviousValueTemplate">
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{TemplateBinding BindingContext.MROViewModel.PreviousValue}" />
<Span Text=" " />
<Span Text="{TemplateBinding BindingContext.MROViewModel.Unit}" />
</FormattedString>
</Label.FormattedText>
</Label>
</ControlTemplate>
</source>
<br>
'''Why This Change?'''
* '''More Modular''': The separation into discrete templates makes individual UI elements reusable and maintainable.
* '''Better Performance''': Eliminates unnecessary loading of UI elements in the background, that are not visible to the user.
<br>
=== Technique 2: Reducing background Binding errors ===
Complex item templates such as UBIKTaskItem were found to produce large numbers of '''errors''' while rendering, likely as bindings are being resolved before the relevant '''viewmodels''' can be loaded by the client. While these '''errors''' are temporary and not visible to the user, the cumulative effect of numerous binding errors raised while rendering items can be felt when navigating to pages with large numbers of items.
<br>
{{Attention|Unfortunately, these bindings errors are not normally logged in the UBIKDebug.log. Therefore, the recommendation is to use the following technique whenever using a ContentControl or controls:ContentControl.}}
==== Previous Approach ====
Initially, we used a '''ContentControl''' with a direct '''ContentTemplate''' and '''TemplateContext''', as shown below:
<tabs>
<tab name="Xamarin">
<source lang = "xml">
xmlns:ctrls="clr-namespace:UBIK.CPL.Controls;assembly=UBIK.CPL"
</source>
</tab>
<tab name="MAUI">
<source lang = "xml">
xmlns:ctrls="clr-namespace:UBIK.MAUI.Controls;assembly=UBIK.MAUI"
</source>
</tab>
</tabs>
<source lang = "xml">
<ctrls:ContentControl
ContentTemplate="{StaticResource TaskPropertyTemplateSelector}"
TemplateContext="{Binding MROViewModel}" />
</source>
<br>
[[File:Binding_logs.png]]
==== Improved Approach ====
One workaround that reduced the number of '''binding errors''' encountered was to refer to '''viewmodels''' indirectly in the bindings.
<source lang = "xml">
<ctrls:ContentControl x:Name="TaskPropertyTempSelCtrl"
BindingContext="{Binding MROViewModel}"
TemplateContext="{Binding BindingContext, Source={x:Reference TaskPropertyTempSelCtrl}}">
</ctrls:ContentControl>
</source>
<br>
The previous example used an '''MROViewModel''' binding directly in the '''TemplateContext''' property of the '''<ctrls:ContentControl>.'''
However, a workaround that seems to avoid triggering background binding errors is to apply the '''MROViewModel''' to the '''<ctrls:ContentControl>''' itself via the '''BindingContext''' property, and then request that '''BindingContext''' using the x:Reference syntax seen in the '''TemplateContext''' property.
'''Why This Change?'''
* '''Avoids Additional Binding Errors''': Using this workaround seems to prevent binding errors.
{{UnderConstructionEnd}}
[[Category:Pages with broken file links|XAML Best practices]]
[[Category:XAML|XAML Best practices]]