|
|
5 years ago | |
|---|---|---|
| XamlNameReferenceGenerator | 5 years ago | |
| XamlNameReferenceGenerator.Sandbox | 5 years ago | |
| .gitignore | 5 years ago | |
| LICENSE | 5 years ago | |
| README.md | 5 years ago | |
| XamlNameReferenceGenerator.sln | 5 years ago | |
README.md
Warning This is just a proof of concept, don't use it for production purposes! There are no unit tests in this project yet. Also, this project hasn't been extensively tested with any other app except for the
XamlNameReferenceGenerator.Sandboxapp.
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 sandbox app is targeting net5 which is still in preview, so this source generator is an early proof-of-concept. The idea is that you include your Avalonia XAML files into your project via <AdditionalFiles Include="**\*.xaml" /> and then decorate your view class with [GenerateTypedNameReferences] and the source generator will look for the xaml (or axaml) file with the same name as your C# class. The source generator then parses the XML markup, finds all XML tags with x:Name attributes and generates the C# code.
Getting Started
So in your project file you write the following code:
<ItemGroup>
<Compile Update="**\*.xaml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<EmbeddedResource Include="**\*.xaml">
<SubType>Designer</SubType>
</EmbeddedResource>
<!-- Note this AdditionalFiles directive. -->
<AdditionalFiles Include="**\*.xaml" />
</ItemGroup>
And then you reference the source generator as such:
<ItemGroup>
<ProjectReference Include="../XamlNameReferenceGenerator/XamlNameReferenceGenerator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
Finally, you declare your view class as partial and decorate it with [GenerateTypedNameReferences]:
[GenerateTypedNameReferences] // Coolstuff!
public partial class SignUpView : Window
{
public SignUpView()
{
AvaloniaXamlLoader.Load(this);
UserNameTextBox.Text = "Joseph"; // Coolstuff!
}
}
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 System;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace XamlNameReferenceGenerator.Sandbox
{
public partial class SignUpView
{
public TextBox UserNameTextBox => this.FindControl<TextBox>("UserNameTextBox");
public TextBlock UserNameValidation => this.FindControl<TextBlock>("UserNameValidation");
public TextBox PasswordTextBox => this.FindControl<TextBox>("PasswordTextBox");
public TextBlock PasswordValidation => this.FindControl<TextBlock>("PasswordValidation");
public TextBox ConfirmPasswordTextBox => this.FindControl<TextBox>("ConfirmPasswordTextBox");
public TextBlock ConfirmPasswordValidation => this.FindControl<TextBlock>("ConfirmPasswordValidation");
public Button SignUpButton => this.FindControl<Button>("SignUpButton");
public TextBlock CompoundValidation => this.FindControl<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] // Coolstuff!
public partial class SignUpView : ReactiveWindow<SignUpViewModel>
{
public SignUpView()
{
AvaloniaXamlLoader.Load(this);
this.WhenActivated(disposables =>
{
// Coolstuff!
this.BindValidation(ViewModel, x => x.UserName, x => x.UserNameValidation.Text)
.DisposeWith(disposables);
this.BindValidation(ViewModel, x => x.Password, x => x.PasswordValidation.Text)
.DisposeWith(disposables);
});
}
}