Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/AvaloniaUI/Avalonia.NameGenerator

Generates x:Name refs to Avalonia XAML controls.
https://github.com/AvaloniaUI/Avalonia.NameGenerator

avalonia avaloniaui csharp dotnet hacktoberfest sourcegenerator xaml xamlx

Last synced: 3 months ago
JSON representation

Generates x:Name refs to Avalonia XAML controls.

Awesome Lists containing this project

README

        

> **Warning** The development of this package has been [**moved**](https://github.com/AvaloniaUI/Avalonia/pull/10407) to the [main AvaloniaUI repository](https://github.com/avaloniaUI/Avalonia). Please consider opening issues or pull requests in the [main AvaloniaUI repository](https://github.com/avaloniaUI/Avalonia). Head over to [AvaloniaUI Gitter](https://gitter.im/AvaloniaUI/Avalonia) or check [AvaloniaUI Discussions](https://github.com/AvaloniaUI/Avalonia/discussions) if you have any questions regarding the migration process.

[![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)

### C# `SourceGenerator` for Typed Avalonia `x:Name` References

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

In order to get started, just install the NuGet package:

```
dotnet add package XamlNameReferenceGenerator
```

Or, if you are using [submodules](https://git-scm.com/docs/git-submodule), you can reference the generator as such:

```xml



```

### Usage

After installing the NuGet package, declare your view class as `partial`. Typed C# references to Avalonia controls declared in XAML files will be generated for classes referenced by the `x:Class` directive in XAML files. For example, for the following XAML markup:

```xml

```

A new C# partial class named `SignUpView` with a single `public` property named `UserNameTextBox` of type `TextBox` will be generated in the `Sample.App` namespace. We won't see the generated file, but we'll be able to access the generated property as shown below:

```cs
using Avalonia.Controls;

namespace Sample.App
{
public partial class SignUpView : Window
{
public SignUpView()
{
// This method is generated. Call it before accessing any
// of the generated properties. The 'UserNameTextBox'
// property is also generated.
InitializeComponent();
UserNameTextBox.Text = "Joseph";
}
}
}
```

### 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
{
public SignUpView()
{
InitializeComponent();
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

> Never keep a method named `InitializeComponent` in your code-behind view class if you are using the generator with `AvaloniaNameGeneratorBehavior` set to `InitializeComponent` (this is the default value). The private `InitializeComponent` method declared in your code-behind class hides the `InitializeComponent` method generated by `Avalonia.NameGenerator`, see [Issue 69](https://github.com/AvaloniaUI/Avalonia.NameGenerator/issues/69). If you wish to use your own `InitializeComponent` method (not the generated one), set `AvaloniaNameGeneratorBehavior` to `OnlyProperties`.

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`
Default value: `InitializeComponent`
Determines if the generator should generate get-only properties, or the `InitializeComponent` method.

- `AvaloniaNameGeneratorDefaultFieldModifier`
Possible values: `internal`, `public`, `private`, `protected`
Default value: `internal`
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`
Default value: `*`
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`
Default value: `*`
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`

- `AvaloniaNameGeneratorViewFileNamingStrategy`
Possible values: `ClassName`, `NamespaceAndClassName`
Default value: `NamespaceAndClassName`
Determines how the automatically generated view files should be [named](https://github.com/AvaloniaUI/Avalonia.NameGenerator/issues/92).

The default values are given by:

```xml


InitializeComponent
internal
*
*
NamespaceAndClassName

```

![](https://user-images.githubusercontent.com/6759207/107812261-7ddfea00-6d80-11eb-9c7e-67bf95d0f0d4.gif)

### What do the generated sources look like?

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 `InitializeComponent` mode:

```cs
//

using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace Sample.App
{
partial class SampleView
{
internal global::Avalonia.NameGenerator.Sandbox.Controls.CustomTextBox UserNameTextBox;
public global::Avalonia.Controls.TextBlock UserNameValidation;
private global::Avalonia.Controls.TextBox PasswordTextBox;
internal global::Avalonia.Controls.TextBlock PasswordValidation;
internal global::Avalonia.Controls.ListBox AwesomeListView;
internal global::Avalonia.Controls.TextBox ConfirmPasswordTextBox;
internal global::Avalonia.Controls.TextBlock ConfirmPasswordValidation;
internal global::Avalonia.Controls.Button SignUpButton;
internal global::Avalonia.Controls.TextBlock CompoundValidation;

public void InitializeComponent(bool loadXaml = true, bool attachDevTools = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}

// This will be added only if you install Avalonia.Diagnostics.
#if DEBUG
if (attachDevTools)
{
this.AttachDevTools();
}
#endif

UserNameTextBox = this.FindNameScope()?.Find("UserNameTextBox");
UserNameValidation = this.FindNameScope()?.Find("UserNameValidation");
PasswordTextBox = this.FindNameScope()?.Find("PasswordTextBox");
PasswordValidation = this.FindNameScope()?.Find("PasswordValidation");
AwesomeListView = this.FindNameScope()?.Find("AwesomeListView");
ConfirmPasswordTextBox = this.FindNameScope()?.Find("ConfirmPasswordTextBox");
ConfirmPasswordValidation = this.FindNameScope()?.Find("ConfirmPasswordValidation");
SignUpButton = this.FindNameScope()?.Find("SignUpButton");
CompoundValidation = this.FindNameScope()?.Find("CompoundValidation");
}
}
}
```

If you enable the `OnlyProperties` source generator mode, you get:

```cs
//

using Avalonia.Controls;

namespace Avalonia.NameGenerator.Sandbox.Views
{
partial class SignUpView
{
internal global::Avalonia.NameGenerator.Sandbox.Controls.CustomTextBox UserNameTextBox => this.FindNameScope()?.Find("UserNameTextBox");
public global::Avalonia.Controls.TextBlock UserNameValidation => this.FindNameScope()?.Find("UserNameValidation");
private global::Avalonia.Controls.TextBox PasswordTextBox => this.FindNameScope()?.Find("PasswordTextBox");
internal global::Avalonia.Controls.TextBlock PasswordValidation => this.FindNameScope()?.Find("PasswordValidation");
internal global::Avalonia.Controls.TextBox ConfirmPasswordTextBox => this.FindNameScope()?.Find("ConfirmPasswordTextBox");
internal global::Avalonia.Controls.TextBlock ConfirmPasswordValidation => this.FindNameScope()?.Find("ConfirmPasswordValidation");
internal global::Avalonia.Controls.Button SignUpButton => this.FindNameScope()?.Find("SignUpButton");
internal global::Avalonia.Controls.TextBlock CompoundValidation => this.FindNameScope()?.Find("CompoundValidation");
}
}
```