Browse Source

docs: Document the new Generator Options (#33)

* docs: Update README.md
* Bump version
pull/10407/head 0.4.1
Artyom V. Gorchakov 6 years ago
committed by GitHub
parent
commit
93b6c0624a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 119
      README.md
  2. 2
      src/Avalonia.NameGenerator/GeneratorOptions.cs
  3. 2
      version.json

119
README.md

@ -1,11 +1,7 @@
[![NuGet Stats](https://img.shields.io/nuget/v/XamlNameReferenceGenerator.svg)](https://www.nuget.org/packages/XamlNameReferenceGenerator) [![downloads](https://img.shields.io/nuget/dt/XamlNameReferenceGenerator)](https://www.nuget.org/packages/XamlNameReferenceGenerator) ![Build](https://github.com/avaloniaui/Avalonia.NameGenerator/workflows/Build/badge.svg) ![License](https://img.shields.io/github/license/avaloniaui/Avalonia.NameGenerator.svg) ![Size](https://img.shields.io/github/repo-size/avaloniaui/Avalonia.NameGenerator.svg)
> **Warning** This tool hasn't been extensively tested, so use at your own risk.
### C# `SourceGenerator` for Typed Avalonia `x:Name` References
<img src="https://hsto.org/webt/6a/j6/v5/6aj6v5vemc3g6zqcks0wm_irg1s.gif" />
This is a [C# `SourceGenerator`](https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/) built for generating strongly-typed references to controls with `x:Name` (or just `Name`) attributes declared in XAML (or, in `.axaml`). The source generator will look for the `xaml` (or `axaml`) file with the same name as your partial C# class that is a subclass of `Avalonia.INamed` and parses the XAML markup, finds all XAML tags with `x:Name` attributes and generates the C# code.
### Getting Started
@ -20,9 +16,8 @@ Or, if you are using [submodules](https://git-scm.com/docs/git-submodule), you c
```xml
<ItemGroup>
<!-- Remember to include XAML files via <AdditionalFiles>,
otherwise C# source generators won't see the XAML files.
If you are using a NuGet package, this is done automatically. -->
<!-- Remember to ensure XAML files are included via <AdditionalFiles>,
otherwise C# source generator won't see XAML files. -->
<AdditionalFiles Include="**\*.xaml"/>
<ProjectReference Include="..\Avalonia.NameGenerator\Avalonia.NameGenerator.csproj"
OutputItemType="Analyzer"
@ -62,9 +57,69 @@ namespace Sample.App
<img src="https://hsto.org/getpro/habr/post_images/d9f/4aa/a1e/d9f4aaa1eb450f5dd2fca66631bc16a0.gif" />
### Why do I need this?
The typed `x:Name` references might be useful if you decide to use e.g. [ReactiveUI code-behind bindings](https://www.reactiveui.net/docs/handbook/data-binding/):
```cs
// UserNameValidation and PasswordValidation are auto generated.
public partial class SignUpView : ReactiveWindow<SignUpViewModel>
{
public SignUpView()
{
AvaloniaXamlLoader.Load(this);
this.WhenActivated(disposables =>
{
this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameValidation.Text)
.DisposeWith(disposables);
this.BindValidation(ViewModel, x => x.Password, x => x.PasswordValidation.Text)
.DisposeWith(disposables);
});
}
}
```
### Advanced Usage
The `x:Name` generator can be configured via MsBuild properties that you can put into your C# project file (`.csproj`). Using such options, you can configure the generator behavior, the default field modifier, namespace and path filters. The generator supports the following options:
- `AvaloniaNameGeneratorBehavior`
Possible values: `OnlyProperties`, `InitializeComponent`
Determines if the generator should generate get-only properties, or the `InitializeComponent` method.
- `AvaloniaNameGeneratorDefaultFieldModifier`
Possible values: `internal`, `public`, `private`, `protected`
The default field modifier that should be used when there is no `x:FieldModifier` directive specified.
- `AvaloniaNameGeneratorFilterByPath`
Posssible format: `glob_pattern`, `glob_pattern;glob_pattern`
The generator will process only XAML files with paths matching the specified glob pattern(s).
Example: `*/Views/*View.xaml`, `*View.axaml;*Control.axaml`
- `AvaloniaNameGeneratorFilterByNamespace`
Posssible format: `glob_pattern`, `glob_pattern;glob_pattern`
The generator will process only XAML files with base classes' namespaces matching the specified glob pattern(s).
Example: `MyApp.Presentation.*`, `MyApp.Presentation.Views;MyApp.Presentation.Controls`
The default values are given by:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AvaloniaNameGeneratorBehavior>OnlyProperties</AvaloniaNameGeneratorBehavior>
<AvaloniaNameGeneratorDefaultFieldModifier>internal</AvaloniaNameGeneratorDefaultFieldModifier>
<AvaloniaNameGeneratorFilterByPath>*</AvaloniaNameGeneratorFilterByPath>
<AvaloniaNameGeneratorFilterByNamespace>*</AvaloniaNameGeneratorFilterByNamespace>
</PropertyGroup>
<!-- ... -->
</Project>
```
![](https://user-images.githubusercontent.com/6759207/107812261-7ddfea00-6d80-11eb-9c7e-67bf95d0f0d4.gif)
### What do the generated sources look like?
For the [`SignUpView` view class](https://github.com/avaloniaui/Avalonia.NameGenerator/blob/main/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml) from [the sandbox project](https://github.com/avaloniaui/Avalonia.NameGenerator/tree/main/Avalonia.NameGenerator.Sandbox), we get the following generated output:
For [`SignUpView`](https://github.com/avaloniaui/Avalonia.NameGenerator/blob/main/src/Avalonia.NameGenerator.Sandbox/Views/SignUpView.xaml), we get the following generated output when the source generator is in the `OnlyProperties` mode:
```cs
// <auto-generated />
@ -87,25 +142,45 @@ namespace Avalonia.NameGenerator.Sandbox.Views
}
```
### Why do I need this?
The typed `x:Name` references might be useful if you decide to use e.g. [ReactiveUI code-behind bindings](https://www.reactiveui.net/docs/handbook/data-binding/):
If you enable the `InitializeComponent` source generator mode, you get:
```cs
// UserNameValidation and PasswordValidation are auto generated.
public partial class SignUpView : ReactiveWindow<SignUpViewModel>
// <auto-generated />
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Sample.App
{
public SignUpView()
partial class SampleView
{
AvaloniaXamlLoader.Load(this);
this.WhenActivated(disposables =>
internal global::Avalonia.NameGenerator.Sandbox.Controls.CustomTextBox UserNameTextBox { get; set; }
public global::Avalonia.Controls.TextBlock UserNameValidation { get; set; }
private global::Avalonia.Controls.TextBox PasswordTextBox { get; set; }
internal global::Avalonia.Controls.TextBlock PasswordValidation { get; set; }
internal global::Avalonia.Controls.ListBox AwesomeListView { get; set; }
internal global::Avalonia.Controls.TextBox ConfirmPasswordTextBox { get; set; }
internal global::Avalonia.Controls.TextBlock ConfirmPasswordValidation { get; set; }
internal global::Avalonia.Controls.Button SignUpButton { get; set; }
internal global::Avalonia.Controls.TextBlock CompoundValidation { get; set; }
public void InitializeComponent(bool loadXaml = true)
{
this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameValidation.Text)
.DisposeWith(disposables);
this.BindValidation(ViewModel, x => x.Password, x => x.PasswordValidation.Text)
.DisposeWith(disposables);
});
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}
UserNameTextBox = this.FindControl<global::Avalonia.NameGenerator.Sandbox.Controls.CustomTextBox>("UserNameTextBox");
UserNameValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("UserNameValidation");
PasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("PasswordTextBox");
PasswordValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("PasswordValidation");
AwesomeListView = this.FindControl<global::Avalonia.Controls.ListBox>("AwesomeListView");
ConfirmPasswordTextBox = this.FindControl<global::Avalonia.Controls.TextBox>("ConfirmPasswordTextBox");
ConfirmPasswordValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("ConfirmPasswordValidation");
SignUpButton = this.FindControl<global::Avalonia.Controls.Button>("SignUpButton");
CompoundValidation = this.FindControl<global::Avalonia.Controls.TextBlock>("CompoundValidation");
}
}
}
```

2
src/Avalonia.NameGenerator/GeneratorOptions.cs

@ -8,7 +8,7 @@ namespace Avalonia.NameGenerator
AvaloniaNameGeneratorBehavior = 0,
AvaloniaNameGeneratorDefaultFieldModifier = 1,
AvaloniaNameGeneratorFilterByPath = 2,
AvaloniaNameGeneratorFilterByNamespace = 2,
AvaloniaNameGeneratorFilterByNamespace = 3,
}
public enum DefaultFieldModifier

2
version.json

@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "0.3.1-preview",
"version": "0.4",
"assemblyVersion": {
"precision": "revision"
},

Loading…
Cancel
Save