Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/AutumnEvans418/Evans.XamlTemplates

This is a templating system that will allow you to create templates in Xamarin.Forms
https://github.com/AutumnEvans418/Evans.XamlTemplates

Last synced: 30 days ago
JSON representation

This is a templating system that will allow you to create templates in Xamarin.Forms

Awesome Lists containing this project

README

        

# Xaml Templates (Work in Progress)
**This project is not production ready and just shows how a template system for xaml could work**

## Reasoning (Why does this exist?)
- Better reuse of components
- Inspired by the razor engine in asp.net core.
- Write less code!
- Mix C# and xaml to generate your view (think razor)
- Compatible with current xaml projects.
- Use as much or as little templates as needed

Additionally, I really **hate** writing
```xml






```
over and over again

I'd rather write this:

```xml

```

We can do this by writing this in our Templates.taml file:

```csharp
@Entry(string Caption, string Text)
{




}
```

This will generate the desired control as seen above

## How it works
1. Install the XamlTemplates.MSBuild nuget to your Xamarin.Forms .net standard project
2. Create a file called ```Templates.taml```
3. Add the following code ```@HelloLabel() { } ```
4. Build the project
5. This should generate ```HelloLabel.xaml``` and ```HelloLabel.xaml.cs```
6. You can now use this template in you xaml like so: ``````

Xaml templates is a templating engine for xamarin forms that allows you to build templates with ease without having to make custom controls.

**Turn 40+ lines of code to just 8**

## Examples
Below is an example of a template in a file called template.taml

**Easily use templates in your xaml app**
![](Assets/example.gif)
**Easy to add and update templates, which update the project on build**
![](Assets/example2.gif)

![](Assets/example3.gif)

### Basic Example

```csharp
@LabelEntry(string label,string Text)
{




}
```
#### Result
This will be generated to the following c# and xaml file

LabelEntry.xaml
```xml






```

LabelEntry.xaml.cs
```csharp
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Evans.XamlTemplates
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class LabelEntry : ContentView
{
public static BindableProperty labelProperty =
BindableProperty.Create(nameof(label), typeof(string), typeof(LabelEntry), default, BindingMode.TwoWay);
public static BindableProperty TextProperty =
BindableProperty.Create(nameof(Text), typeof(string), typeof(LabelEntry), default, BindingMode.TwoWay);
public LabelEntry()
{
InitializeComponent();
_Label.BindingContext = this;
_Entry.BindingContext = this;
_Label.SetBinding(Label.TextProperty,nameof(label));
_Entry.SetBinding(Entry.TextProperty, nameof(Text));
}
public string label
{
get => (string)GetValue(LabelProperty);
set => SetValue(LabelProperty, value);
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
}
}
```

### Third Party Controls
Third party work out of the box
```csharp
@DataGridSection(string Header, IEnumerable Data)
{

}
```

You can also place templates in other templates

```csharp
@DataGridSection(string HeaderText, IEnumerable Data)
{




}
```

### More Advanced Example

```csharp
@EntryAndPicker(string Label,string Text, IEnumerable data, string selectedItem)
{






}
```
#### Result

```xml










```

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Evans.XamlTemplates
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EntryAndPicker : ContentView
{
public static BindableProperty LabelProperty =
BindableProperty.Create(nameof(Label), typeof(string), typeof(EntryAndPicker), default, BindingMode.TwoWay);
public static BindableProperty TextProperty =
BindableProperty.Create(nameof(Text), typeof(string), typeof(EntryAndPicker), default, BindingMode.TwoWay);

public static BindableProperty dataProperty =
BindableProperty.Create(nameof(data), typeof(IEnumerable), typeof(EntryAndPicker), default, BindingMode.TwoWay);
public static BindableProperty selectedItemProperty =
BindableProperty.Create(nameof(selectedItem), typeof(string), typeof(EntryAndPicker), default, BindingMode.TwoWay);

public EntryAndPicker()
{
InitializeComponent();
_Label.BindingContext = this;
_Entry.BindingContext = this;
_Label1.BindingContext = this;
_Picker.BindingContext = this;
_Label2.BindingContext = this;
_Label.SetBinding(Xamarin.Forms.Label.TextProperty, nameof(Label));
_Entry.SetBinding(Xamarin.Forms.Entry.TextProperty,nameof(Text));
_Label1.SetBinding(Xamarin.Forms.Label.TextProperty, nameof(Text));
_Picker.SetBinding(Xamarin.Forms.Picker.ItemsSourceProperty, nameof(data));
_Picker.SetBinding(Xamarin.Forms.Picker.SelectedItemProperty, nameof(selectedItem));
_Label2.SetBinding(Xamarin.Forms.Label.TextProperty, nameof(selectedItem));
}

public string Label
{
get => (string)GetValue(LabelProperty);
set => SetValue(LabelProperty, value);
}
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}

public IEnumerable data
{
get => (IEnumerable)GetValue(dataProperty);
set => SetValue(dataProperty, value);
}
public string selectedItem
{
get => (string)GetValue(selectedItemProperty);
set => SetValue(selectedItemProperty, value);
}
}
}

```

Notice how much code it takes to just make a template? There needs to be a simpler solution

## Limitations
There are several limitations to Xaml Templates
- Xaml templates relies on xml linq and doesn't support nested attributes, such as ``````
- The generated templates may not be optimized. For example, repeating label and entries may be more effecient than placing them in stack layouts.
- The razor style csharp code is not type checked, meaning if you put ```supertype test = blah``` as a parameter, it will generate. Although, your project won't build, so it may still be obvious that the syntax is invalid

# Developers

## Prerequisite

- dotnet core 3.1
- Xamarin.Forms

## How to build
Run the `build.ps1` script

- Run the ```packAndUpdate.ps1``` powershell script. This will update the msbuild task and add it to the Evans.XamlTemplates Project
- Right click solution -> Build Solution

## Feature List

- [x] Allow to nest templates, such as one template calling another
- [x] Support third party controls, such as syncfusion
- [x] Default value support for parameters ex. ```string test = "test"```
- [ ] Allow the use of ```@if``` statements
- [ ] Support ```@foreach``` statements
- [x] Add example project
- [x] Create example website
- [ ] Support WPF
- [ ] Support UWP
- [x] Support Xamarin.Forms
- [x] Add parameters to MSBuild that can be customized
- [x] Add generated code warning
- [x] Add line to the error message
- [ ] Add syntax highlighting for taml files
- [ ] Add ability to generate c# methods and event handling
- [x] Support Comments
- [ ] Support Xml Dot Attributes
- https://docs.microsoft.com/en-us/dotnet/desktop-wpf/xaml-services/basic-reading-writing
- [ ] Support different base types other than ContentView, such as StackLayout, Grid, etc.

# Analysis

## What needs to be known?

- ClassName
- Parameters (Comma Seperated)
- Name of Parameter
- Type of Parameter
- Controls With Bindings
- Control Type
- Control name (Label1, label2, etc...)
- Bindings on control
- Control Type
- Control Property
- Bindable Property

## Logic
```csharp
foreach parameter
- create a bindable property
- create a property
foreach control
- Set binding context to this
foreach binding on control
- set binding for control
```

# Resources

## Useful Scripts
In the msbuild task
```.\nuget.exe pack .\XamlTemplates.MSBuild.nuspec```
You can then add the package using the following command:
```dotnet add package XamlTemplates.MSBuild```
**Note: this works because Nuget.config defines a custom location for the nuget packages**

- Based off my compilers project
- creating an msbuild task:
- https://blog.rsuter.com/implement-custom-msbuild-tasks-and-distribute-them-via-nuget/