CommunityToolkit / CommunityToolkit/dotnet

[MVVM] `AttachedProperty`/`DirectProperty`/`StyledProperty` source generators

Open
#1,203 0 comments 1 reaction 0 assignees View on GitHub
feature request :mailbox_with_mail:
Dominant language
C#
Stars
3.8k
Forks
400
PR merge metrics
No merged PRs in 30d

Description

### Overview

Examples like these require a considerable amount of repetitive code:
```cs
public bool Foo
{
get => GetValue(FooProperty);
set => SetValue(FooProperty, value);
}

public ObservableCollection? BarsSource
{
get => GetValue(BarsSourceProperty);
set => SetValue(BarsSourceProperty, value);
}

public ICommand? BazCommand
{
get => GetValue(BazCommandProperty);
set => SetValue(BazCommandProperty, value);
}

public static readonly StyledProperty FooProperty =
AvaloniaProperty.Register(nameof(Foo));

public static readonly StyledProperty?> BarsSourceProperty =
AvaloniaProperty.Register?>(nameof(BarsSource));

public static readonly StyledProperty BazCommandProperty =
AvaloniaProperty.Register(nameof(BazCommand));
```

### API breakdown

```cs
namespace CommunityToolkit.Mvvm.ComponentModel;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class AttachedPropertyAttribute : Attribute;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class DirectPropertyAttribute : Attribute;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class StyledPropertyAttribute : Attribute;
```

### Usage example

`QuxControl.cs`
```cs
public partial class QuxControl : Panel
{
[StyledProperty]
public partial bool Foo { get; set; }

[StyledProperty]
public partial ObservableCollection? BarsSource { get; set; }

[StyledProperty]
public partial ICommand? BazCommand { get; set; }
}
```
`MyProject.Views.QuxControl.g.cs`
```cs
namespace MyProject.Views
{
partial class QuxControl
{
/* ... */
public partial bool Foo
{
get => GetValue(FooProperty);
set => SetValue(FooProperty, value);
}

/* ... */
public partial ObservableCollection? BarsSource
{
get => GetValue(BarsSourceProperty);
set => SetValue(BarsSourceProperty, value);
}

/* ... */
public partial ICommand? BazCommand
{
get => GetValue(BazCommandProperty);
set => SetValue(BazCommandProperty, value);
}

/* ... */
public static readonly StyledProperty FooProperty =
AvaloniaProperty.Register(nameof(Foo));

/* ... */
public static readonly StyledProperty?> BarsSourceProperty =
AvaloniaProperty.Register?>(nameof(BarsSource));

/* ... */
public static readonly StyledProperty BazCommandProperty =
AvaloniaProperty.Register(nameof(BazCommand));
}
}
```

### Breaking change?

No

### Alternatives

There are existing packages (https://github.com/jp2masa/Avalonia.PropertyGenerator, https://github.com/lucdem/AvaSourceGenerators) that don't entirely work in the proposed way.

### Additional context

_No response_

### Help us help you

No, just wanted to propose this

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.