Jump to: navigation, search

Difference between revisions of "XAML Best practices"


m
m (Formatting)
Line 23: Line 23:
 
{{Hint|If you struggle to maintain nice formatting while writing your xaml code, you can find formatters that automatically such as Notepad++’s “Pretty Print” or VS Code’s “XAML Styler” plugins.}}
 
{{Hint|If you struggle to maintain nice formatting while writing your xaml code, you can find formatters that automatically such as Notepad++’s “Pretty Print” or VS Code’s “XAML Styler” plugins.}}
  
The most important points are marked with a 🏆
+
==== Best Practices ====
  
 
* x: Name or x: Key should come first.
 
* x: Name or x: Key should come first.
Line 67: Line 67:
 
  <nowiki><!--#region Text Styles-->, <!--#region DataTemplates-->, or <!--#region Item Templates--></nowiki>.
 
  <nowiki><!--#region Text Styles-->, <!--#region DataTemplates-->, or <!--#region Item Templates--></nowiki>.
  
 +
[[Category:Pages with broken file links|XAML Best practices]]
 +
[[Category:XAML|XAML Best practices]]
  
 
== Performance ==
 
== Performance ==

Revision as of 10:04, 24 June 2024

Wiki Under Construction Start.PNG
This article recommends approaches to customizing and troubleshooting your UBIK custom UIs. To learn about the fundamentals of XAML, check out our article XAML Basics.

Conventions

Conventions are ‘rules’ that make our xamls collectively readable and shareable. By aiming to construct our xaml files in a similar style, we reduce the effort required by others to read and understand our work. This section includes guidelines on how to name controls, and how to internally organize your xaml files.

Naming Conventions

<Button x:Name="SubmitFormButton" ... />
  • The x:Name is used to give a unique name for an object within a xaml file. It’s not valid in a ResourceDirectory (such as a style, template, etc, either defined within a xaml file, or in UBIKThemes), which requires using x:Key instead.
    • Likewise there is a difference when referencing x:Name and x:Key elements.
x:Name - UWP: ElementName=SubmitFormButton | Xamarin: Source={x:Reference  SubmitFormButton}
 x:Key - Both: {StaticResource SubmitFormButtonStyle} or {DynamicResource SubmitFormButtonStyle}
  • Use explicit language when giving a name or key, for example: “PropStkpnl” is not easily readable, but “PropertiesStackPanel” is.
  • Furthermore, “FailureCodeExpression” does not describe the purpose of the expression, whereas “FailureCode_HasUnfilledFields” does.
    • Naming it according to its purpose also makes it easier to use in xaml, such as when combining the result with a converter for an intended outcome (eg. An warning symbol visible when FailureCode_HasUnfilledFields is true).
  • You do not have to name every object in your code, only if it is referred to by another element. However, sometimes adding names to controls helps a reader understand their intended function.

Formatting

Formatting xamls properly is critical to others being able to quickly read and understand a customizing.

IC Hint square.pngIf you struggle to maintain nice formatting while writing your xaml code, you can find formatters that automatically such as Notepad++’s “Pretty Print” or VS Code’s “XAML Styler” plugins.

Best Practices

  • x: Name or x: Key should come first.
  • A control with up to 2 Attributes can be added in one line. If it has more than 2, they should be stacked over another for readability.
    • Avoid using a formatter where the indentation matches the name of the control

Formatting Indentation.jpg

  • Add controls in a Top-to-Bottom order in the xaml file. Additionally, try to add them in a Left-to-Right order.
    • Controls in Grid.Row/Column 0 should be higher up in your xaml file than controls placed in other rows and columns.
  • Respect indentation of nested controls.
    • Opening and closing tags should always begin in the same column.
    • Controls nested inside them should begin exactly one column to the right.
    • When pasting code snippets into your work, be sure to correct the differences in indentations.
  • Use Linebreaks mindfully.
    • It is difficult to describe rules for how linebreaks should be used, but the general idea is to use them to group elements in your xaml file, and to show which controls are nested (no linebreaks) and which controls are 'siblings' (divided by linebreaks).
    • ✔️Put linebreaks in between large sections of a UI definition (eg. between Grids or major elements of the page, or between content set on different Rows/Columns).
    • ❌ Avoid linebreaks in the middle of smaller elements (eg. a stackpanel with 2 texts inside).
  • 🏆 Add comments.
    • This is one of the most critical features of clear code, saving the reader from wasting time struggling to read the code, or even having to search and ask around.
    • Use comments to describe the position, purpose, and function of every control.
    • When maintain xamls according to a ticket, put the ticket number in a comment so a reader has access to background information on the change.

Formatting Comments.jpg.

  • Remove unnecessary code. Ensure everything included in your xaml has a purpose. This includes large sections of commented out code.
    • This both makes the xaml clearer, but also improves performance by avoiding unnecessary loading and rendering effort.
    • This is especially true when copying from other’s work.
    • If you’re not sure if something is necessary, comment it out and see if your xaml still fulfils its function. If it works, remove it.
    • Read more in the next section on Performance.
  • 🏆 Empty out your UBIKThemes for a new customizing.
    • When working in Xamarin, it is recommended to empty out your UBIKThemes file (ie. delete everything between the <ResourceDictionary> tags) and only add what you intend to customize.
    • Unfortunately, this approach is currently not 100% possible in UWP xamls, as we noticed that custom styles are not utilized on controls unless the controls are also in UBIKThemes, shown instead using the standard grey/orange. However, diligent customizers can find out how to do so below:
      An issue with dynamically refreshing style resources causes emptying of UBIKThemes to be much more complicated on UWP than in Xamarin.
      This is because StaticResources are only updated once they are overwritten again in Themes. The most common symptom of this issue is that for example, if UBIKAccentColor is changed to blue, this customization will not be reflected by styles for any control defined in UBIKThemes, unless the styles are 'written' again in UBIKThemes. So in this example, the regular button hover state will remain orange, unless UBIKButtonStyle is included in the UBIKThemes of that project.
      Therefore, the only approach we can recommend is to remove everything from UBIKThemes, and add styles back once they fail to reflect the customized color resources. Since this approach is impractical, we do not encourage emptying UBIKThemes for UPW as strongly as we do for Xamarin.


  • Organize UBIKThemes in sections.
    • For example, standard UBIKThemes defines resources grouped into; Color resource / Size resources / Text styles / Button styles / etc
    • In Xamarin, keep Item Templates at the end of UBIKThemes.
    • Either way, it is recommended to keep your UBIKThemes file as lean as possible (read the next point), as well as maintaining a grouping strategy. Use the tags <!--#region Example--> and <!--#endregion--> to define groups of content, for example
<!--#region Text Styles-->, <!--#region DataTemplates-->, or <!--#region Item Templates-->.

Performance

A basic rule is that more code = more to compile, and this can decrease the performance of your whole application. To counter that, always attempt to reduce the amount of xaml customizing, especially if you find yourself repeating specific controls and attributes.

Understanding Templating in UBIK

The most critical thing to understand about customizing your UI is that templates for the entire default UI are already present in the client’s core. Customizing templates allow us to modify of specific areas of the UI by overwriting the parts of the default UI with the same name. Therefore, only the specific xamls that need to be customized should be added. This is recommended for many reasons;

  • Custom xamls will ‘undo’ improvements to the UI coming from newer versions of the client, when they are based on xaml files from an older version of UBIK. For custom UIs there is no way around it, but this is why uncustomized copies of xamls should never be added to the project folder. To remove a customizing, simply delete that file. There is no need to replace it with an uncustomized version from the default folder.
  • Less xaml files to parse means better performance.
  • More xamls also makes it more difficult for others to read and understand the customizing. This also makes it much more difficult to find and diagnose errors when requesting support. It also generally increases the effort required to maintain the xamls.

Best Practices

  • 🏆 Deploy a new Default folder every time you your client version, to ensure that the latest UI version is the foundation for your customizing.
  • 🏆 Only include xamls that are needed for your customizing.
    • Remove files for child Areas and Items that are not included in this project.

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 textbox, selection, datetime, geo coordinates, etc).

The logical tree used by these selectors to render different UIs is documented in our article UBIK Templates.










Wiki Under Construction End.PNG

Performance

Diminishing the performance should not be the first priority but it also shouldn’t be the last. You should always think about retaining readability and consistency in your code by adding comments and using clear and significant code. But you also have to keep in mind that more code and lines mean more compiling, this can decrease the performance of your whole application. Just try to keep a good balance between these two factors in order to ease the life of customizers. They’ll surely stumble across your code in a few months and will maybe have a hard time to finalize a ten-minute task because they have to find out what every piece of code exactly does. Here are some examples which support the increase of performance.
For example:

  • If you use the same resource on more than one XAML file, consider defining it in UBIKThemes (Resources Folder -> LocalState/XAML) rather than on each page.
  • Don't define UI elements you don't need for composition and use the default control templates whenever possible (these templates have already been tested and verified for load performance).

Useful links for inefficient XAML code:

Using 'NextLevel' bindings

Performance can be impacted by attempting to show multiple levels of data (ie. child data, from the parent object) outside what is delivered by UBIK by default.

For an in-depth explanation, and guidance on how to implement such functionality safely, please refer to this page Object hierarchy in XAML: NextLevel, ParentLevel, LinkedLevel.


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.