|
|
5 years ago | |
|---|---|---|
| .github/workflows | 5 years ago | |
| external | 5 years ago | |
| src | 5 years ago | |
| .gitignore | 5 years ago | |
| .gitmodules | 5 years ago | |
| LICENSE | 5 years ago | |
| README.md | 5 years ago | |
| version.json | 5 years ago | |
README.md
Warning This tool hasn't been extensively tested, so use at your own risk.
C# SourceGenerator for Typed Avalonia x:Name References

This is a C# SourceGenerator 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, you can reference the generator as such:
<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. -->
<AdditionalFiles Include="**\*.xaml"/>
<ProjectReference Include="..\Avalonia.NameGenerator\Avalonia.NameGenerator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
Usage (Default)
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 all classes that inherit from the Avalonia.INamed interface (including those classes that inherit from Window, UserControl, ReactiveWindow<T>, ReactiveUserControl<T>). For example, for the following XAML markup:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBox x:Name="UserNameTextBox" x:FieldModifier="public" />
</Window>
A new C# public property named UserNameTextBox of type TextBox will be generated:
using Avalonia.Controls;
public partial class SignUpView : Window
{
public SignUpView()
{
AvaloniaXamlLoader.Load(this);
UserNameTextBox.Text = "Joseph"; // Cool stuff!
}
}
Usage (Opt-in)
If you don't want to generate typed x:Name references for every window or user control in your assembly, you can always turn off this default behavior by setting the AvaloniaNameGenerator MsBuild property to false in your C# project file (.csproj). Just add the following property group to your <Project /> tag:
<PropertyGroup>
<AvaloniaNameGenerator>false</AvaloniaNameGenerator>
</PropertyGroup>
From now on, the source generator will process only those files that are decorated with the [GenerateTypedNameReferences] attribute. Other window or user control classes will be left unchanged, and you won't have to mark them as partial.
using Avalonia.Controls;
[GenerateTypedNameReferences]
public partial class SignUpView : Window
{
public SignUpView()
{
AvaloniaXamlLoader.Load(this);
UserNameTextBox.Text = "Joseph"; // Cool stuff!
}
}

What do the generated sources look like?
For the SignUpView view class from the sandbox project, we get the following generated output:
// <auto-generated />
using Avalonia.Controls;
namespace Your.View.Namespace
{
partial class SignUpView
{
internal global::Avalonia.NameGenerator.Sandbox.Controls.CustomTextBox UserNameTextBox => this.FindControl<global::Avalonia.NameGenerator.Sandbox.Controls.CustomTextBox>("UserNameTextBox");
public global::Avalonia.Controls.TextBlock UserNameValidation => this.FindControl<global::Avalonia.Controls.TextBlock>("UserNameValidation");
private global::Avalonia.Controls.TextBox PasswordTextBox => this.FindControl<global::Avalonia.Controls.TextBox>("PasswordTextBox");
internal global::Avalonia.Controls.TextBlock PasswordValidation => this.FindControl<global::Avalonia.Controls.TextBlock>("PasswordValidation");
internal global::Avalonia.Controls.TextBox ConfirmPasswordTextBox => this.FindControl<global::Avalonia.Controls.TextBox>("ConfirmPasswordTextBox");
internal global::Avalonia.Controls.TextBlock ConfirmPasswordValidation => this.FindControl<global::Avalonia.Controls.TextBlock>("ConfirmPasswordValidation");
internal global::Avalonia.Controls.Button SignUpButton => this.FindControl<global::Avalonia.Controls.Button>("SignUpButton");
internal global::Avalonia.Controls.TextBlock CompoundValidation => this.FindControl<global::Avalonia.Controls.TextBlock>("CompoundValidation");
}
}
Why do I need this?
The typed x:Name references might be useful if you decide to use e.g. ReactiveUI code-behind bindings:
[GenerateTypedNameReferences] // 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);
});
}
}