havendv / dependencypropertygenerator Goto Github PK
View Code? Open in Web Editor NEWDependency property, routed event and weak event source generator for WPF/UWP/WinUI/Uno/Avalonia/MAUI platforms.
License: MIT License
Dependency property, routed event and weak event source generator for WPF/UWP/WinUI/Uno/Avalonia/MAUI platforms.
License: MIT License
I'm trying to declare a property for a custom YearMonthPicker. I'm adding a string property, and I'm expecting it not to be null because I'll be providing a default value. However, even tho the property itself is not marked as nullable, the generated code is:
/// <summary>
/// Default value: "MMMM yyyy"
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DependencyPropertyGenerator", "1.4.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public string? StringFormat
{
get => (string?)GetValue(StringFormatProperty);
set => SetValue(StringFormatProperty, value);
}
Declare a class, and add the following attribute:
[DependencyProperty<string>("StringFormat", DefaultValue = "MMMM yyyy")]
/// <summary>
/// Default value: "MMMM yyyy"
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCode("DependencyPropertyGenerator", "1.4.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public string StringFormat
{
get => (string)GetValue(StringFormatProperty);
set => SetValue(StringFormatProperty, value);
}
No response
1.4.0
Visual Studio 2022
No response
hey there, I've been using your library https://github.com/HavenDV/DependencyPropertyGenerator for a while (it's awesome!). The main issue I've been running in to is that both Visual Studio and Rider seem to eventually stop generating source for intellisense. This never breaks a full roslyn compile (eg. F6) but makes coding almost impossible as you get hundreds or thousands of intellisense errors obscuring the real compiler errors. Restarting VS or Rider always fixes the issue. Other source generators in the same solution do not seem to be affected by this same problem.
In Rider this is really reproducible, I can just add a default value, save the file, remove the default value, save, and now the intellisense is permanently broken until I restart Rider. In VS the problem seems to happen after some time randomly, and I can't reproduce reliably.
Is this something you've encountered before?
Haven — 11/09/2022
Hi, thank you. Yes, I encounter this too. If you say that other generators are not affected by this, then perhaps this is a problem in my code. Can you tell me which generators exactly work in similar scenarios so that I can examine their code in more detail?
I have little experience with Rider, in VS I only experience problems if I install a NuGet package in a new project and need to restart VS for the generator to work correctly in intellisense.
There is also a chance that this is a problem with the Rider. But, in any case, it would be great to look into and let them know if so
caesay — 11/09/2022
I initially switched to VS from Rider because of this issue (but then it started happening in VS too.. just a little less frequently)
It seems to happen when I am editing the DependencyProperty attributes a lot, then randomly VS will just stop generating source until I restart.
caesay — 11/09/2022
Happy to provide any logs if you think there is something that would be useful to test. As far as other source generators - I am using https://github.com/CollinAlpert/Lombok.NET also. After the Dependency property problem, Lombok continues to generate source - but all the generated dependency properties are missing until IDE restart
I have just confirmed that the dependency property problems happen with and without the lombok source generator in the project
Haven — 11/09/2022
Many ideas and structure of my generator are from https://github.com/andrewlock/NetEscapades.EnumGenerators. This is especially true for the compile time delivery of an additional library for attributes, which is excluded from the final build. Perhaps this is the problem and I will be grateful if you can check this generator in your project
caesay — 11/09/2022
in Rider seems to have the same issue. as soon as you start editing the EnumExtensions attribute it stops generating code for EnumGenerators. The DependencyProperty source is still available at that point. Hard to reproduce in VS as the issues are intermittent.
caesay — 11/09/2022
I managed to enable roslyn tracing in Rider. Here is a log of when it's working for a particular project https://pastie.io/raw/jivjci, and a log after it breaks https://pastie.io/raw/endqba. Not particularly helpful. DependencyPropertyGenerator is detected both times, but in the broken run it just doesn't output any files.
Can see there though that they break independently. I edited a DependencyPropertyGenerator attribute, so it stopped generating code but the EnumGenerator source generator still output a file.
Haven — 11/09/2022
Please try to add this to your .csproj and exclude compile assets:
<DependencyPropertyGenerator_EmbedAttributes>true</DependencyPropertyGenerator_EmbedAttributes>
123
No response
No response
No response
No response
No response
At the moment, the events generated by this feature need to be injected by yourself, specifying a compatible method signature
Hi,
I've trying to get this generator to work with an existing WPF project.
DependencyPropertyGenerator does not seem to work when the project has other packages with custom targets. For example CompiledBindings
I thought that is was just not passing the DefineConstants but that doesn't seem to be the case:
The generated editorconfig also seems to have the correct data:
build_property.RecognizeFramework_DefineConstants = TRACE,HAS_WPF,DEBUG,NET,NET8_0,NETCOREAPP
build_property.UseWPF = true
Please see attached repro.
DependencyPropertyGeneratorTest.zip
I've also included another project with a launch profile to help with debugging the source generator. To use:
Interestingly it looks like it detects the framework when run from the debugger just not when building the actual project.
No response
No response
1.4.0
Visual Studio 2022
I've tried adding a .props file as recommended in https://github.com/HavenDV/H.Generators.Extensions but no luck there.
With the roslyn debugger on a PackageReference the CompilerAnalyzerConfigOptions.GlobalOptions looks like
I cloned the main branch to see if there was difference when using ProjectReference instead and when using the debugger the CompilerAnalyzerConfigOptions.GlobalOptions looks like
From chat:
Sergio UI Variable — 01/19/2023 6:47 PM
That generator is not incremental :Smadge:
Haven — 01/19/2023 6:58 PM
Are you talking about DependencyPropertyGenerator? It is incremental.
https://github.com/HavenDV/DependencyPropertyGenerator/blob/77cc3d352923beef89838bb9c10132f407e31e62/src/libs/DependencyPropertyGenerator/DependencyPropertyGenerator.cs#L16
Dongle — 01/19/2023 6:59 PM
Teach me how to make one, I'm kinda needing one RN (having a thread open)
Sergio UI Variable — 01/19/2023 7:09 PM
It's completely not incremental
Yes it implements IIncrementalGenerator, but it's completely not incremental
It's as good as if you had used ISourceGenerator (if not worse, potentially)
Haven — 01/19/2023 7:25 PM
Thanks, I read about it and I think I'm starting to understand what you mean. I think you mean caching at each step, so the generator doesn't do the same thing over and over again.
Initially, I understood the IIncrementalGenerator interface as something that allows you to react only to code changes associated with the generator. For example, in this case, I thought that only changing the attributes provided by a given generator would cause the code to be regenerated. Whereas ISourceGenerator would regenerate the code whenever the code changes.
Sergio UI Variable — 01/19/2023 7:30 PM
Yes. But currently, your generator would redo everything for every single key press
Regardless of whether anything related to it has actually changed or not
So in practice your generator is not incremental
(as I said it might actually be slower than an "original" non incremental one)
Haven — 01/19/2023 7:37 PM
Ok, thank you for pointing this out, I'll investigate this further
References:
https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md
https://github.com/CommunityToolkit/dotnet/blob/main/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.cs
https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen
No response
No response
No response
Visual Studio 2022
No response
A warning is generated when there are properties in different assemblies.
Create two class libraries ClassLibraryA and ClassLibraryB.
In ClassLibraryA add:
[DependencyProperty<int>("Property1")]
public partial class Control1 : Control
{
}
In ClassLibraryB add:
[DependencyProperty<int>("Property2")]
public partial class Control2 : Control
{
}
In ClassLibraryB add a reference to ClassLibraryA.
Warnings are generated when compiling ClassLibraryB.
No warning should be generated.
No response
1.3.0
Visual Studio 2022
In a WPF class project.
In the latest pre-release of Avalonia 11 (preview 6), the prototype of the Register method with the parameter notifying
is now internal.
Here a discussion on the Avalonia repo explaining the change: AvaloniaUI/Avalonia#10766
So your library cannot be used with this version and the later ones.
11.0.0-preview6
The project no longer builds.
No response
No response
No response
No response
No response
The code generated for primitive type array or for string array is wrong.
With this property:
[DependencyProperty<double[]>("Values")]
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
The generated code is:
public partial class MainWindow
{
/// <summary>
/// Identifies the <see cref="Values"/> dependency property.<br/>
/// Default value: default(double[])
/// </summary>
public static readonly global::System.Windows.DependencyProperty ValuesProperty =
global::System.Windows.DependencyProperty.Register(
name: "Values",
propertyType: typeof(global::double[]),
ownerType: typeof(global::DependencyPropertyGeneratorSimpleType.MainWindow),
typeMetadata: new global::System.Windows.FrameworkPropertyMetadata(
defaultValue: default(global::double[]),
flags: global::System.Windows.FrameworkPropertyMetadataOptions.None,
propertyChangedCallback: null,
coerceValueCallback: null,
isAnimationProhibited: false),
validateValueCallback: null);
/// <summary>
/// Default value: default(double[])
/// </summary>
public global::double[]? Values
{
get => (global::double[]?)GetValue(ValuesProperty);
set => SetValue(ValuesProperty, value);
}
partial void OnValuesChanged();
partial void OnValuesChanged(global::double[]? newValue);
partial void OnValuesChanged(global::double[]? oldValue, global::double[]? newValue);
}
global::
should not be used for primitive type and for string.
No response
1.2.6
Visual Studio 2022
In a WPF project
Can't compile
Mark class with [DependencyProperty<int?>("Property")]
No response
No response
No response
No response
No response
If I add a dependency property with the same name in two classes which have the same name but in two different namespaces then the properties are not generated.
This code generates the error:
using DependencyPropertyGenerator;
using System.Windows;
using System.Windows.Controls;
namespace Namespace1
{
[DependencyProperty<int>("MyProperty")]
public partial class MyControl : UserControl
{
public int MyPropertySqrt => MyProperty * MyProperty;
}
}
namespace Namespace2
{
[DependencyProperty<int>("MyProperty")]
public partial class MyControl : UserControl
{
public int MyPropertySqrt => MyProperty * MyProperty;
}
}
The properties should be generated in both classes.
This code works:
using System.Windows;
using System.Windows.Controls;
namespace Namespace1
{
public partial class MyControl : UserControl
{
public int MyPropertySqrt => MyProperty * MyProperty;
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), new PropertyMetadata(0));
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
}
}
namespace Namespace2
{
public partial class MyControl : UserControl
{
public int MyPropertySqrt => MyProperty * MyProperty;
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(MyControl), new PropertyMetadata(0));
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
}
}
No response
1.2.5
Visual Studio 2022
In a WPF project.
Cool project, thank you for creating something like this!
Type isn't generating correctly when a partial handler for dependency property exists and [DesignTimeVisible(false)]
is set:
Error DPG001 System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
If the attribute has no parameters, this is the error instead:
Error DPG001 System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
[DependencyProperty("Text", typeof(string))]
[DesignTimeVisible(false)]
public partial class Generatable : FrameworkElement
{
partial void OnTextChanged(string oldValue, string newValue)
{
}
}
or
[DependencyProperty("Text", typeof(string))]
[DesignTimeVisible]
public partial class Generatable : FrameworkElement
{
partial void OnTextChanged(string oldValue, string newValue)
{
}
}
It generates
No response
0.34.1
Visual Studio 2022
No response
When creating a StyledProperty
via for example:
[DependencyProperty<int>("SelectedType")]
The resulting generated code does never call the OnSelectedTypeChanged(...)
event handler, subsequently no event notifications when the value changes are received.
The same property as a DirectProperty
:
[DependencyProperty<int>("SelectedType", IsDirect = true)]
contains the necessary calls on all versions of the OnSelectedTypeChanged(...)
event handler in the property setter.
I understand that event handlers for value changes have become a bit cumbersome, as the notifying
parameter has become internal (as of Avalonia 11 preview 6), and as such is not available anymore. The preferred route to receive event notifications is to either override the OnPropertyChanged
method, or attach to the PropertyChange
event. (as per Max Katz from AvaloniaUI core developer team)
Create StyledProperty
in an Avalonia project and try to listen for value changes, which will not fire.
No response
No response
1.2.5
Visual Studio 2022
No response
oldValue
and newValue
might not be used in
static partial void OnPropertyChanged (T sender, int oldValue, int newValue)
Implement the examples in the readme file
There needs to be a way to opt out of that generation. Either by default or explicitly. Here are some options:
GenerateOldValue = true
SkipOldValue = true
GenerateParameters = Gen.OldValue | Gen.NewValue
Alternatively use suppressor to suppress this warning.
0.34.3
Visual Studio 2022-preview
No response
The code generated for multidimensional array is wrong.
int[,]
is replaced with int[*,*]
.
int[,,]
is replaced with int[*,*,*]
.
And so on...
[DependencyProperty<int[]>("Values1")]
[DependencyProperty<int[,]>("Values2")]
[DependencyProperty<int[,,]>("Values3")]
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
int[,]
should remains int[,]
.
int[,,]
should remains int[,,]
.
And so on...
No response
1.2.7
Visual Studio 2022
In a WPF project.
The class generated to implement a dependency property is always set to public.
This is a issue to internal user controls.
The code bellow don't compile:
[DependencyProperty("MyProperty", typeof(....))]
internal partial class MyUserControl : UserControl
{
...
}
My suggestion is to not write any modifiers in the generated code and let the user to put it in the manually written code.
No response
1.3.2
Visual Studio 2022-preview
No response
The generated code for tuples is right but the comment for the default value is wrong.
The comment for (int, string)
is right:
/// Default value: default((int, string))
The comment for (Control, int)
is wrong:
/// Default value: default(Control, int))
The comment for (int, Control)
is wrong:
/// Default value: default(Control))
The comment for System.Tuple<int, string>
is right:
/// Default value: default(Tuple<int, string>)
The comment for System.Tuple<Control, int>
is wrong:
/// Default value: default(Control, int>)
The comment for System.Tuple<int, Control>
is wrong:
/// Default value: default(Control>)
[DependencyProperty<(int, string)>("TypeIntString")]
[DependencyProperty<(Control, int)>("TypeControlInt")]
[DependencyProperty<(int, Control)>("TypeIntControl")]
[DependencyProperty<System.Tuple<int, string>>("TupleIntString")]
[DependencyProperty<System.Tuple<Control, int>>("TupleControlInt")]
[DependencyProperty<System.Tuple<int, Control>>("TupleIntControl")]
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
The comment for (Control, int)
should be:
/// Default value: default((Control, int))
The comment for (int, Control)
should be:
/// Default value: default((int, Control))
The comment for System.Tuple<Control, int>
should be:
/// Default value: default(Tuple<Control, int>)
The comment for System.Tuple<int, Control>
is wrong:
/// Default value: default(Tuple<int, Control>)
No response
1.2.8
Visual Studio 2022
In a WPF project.
Type parameter of the same class doesn't generate method call
[AttachedDependencyProperty<Test, FrameworkElement>("TestProp", OnChanged = nameof(TestChanged))]
public partial class Test
{
private static void TestChanged(FrameworkElement element, Test newValue)
{
}
}
Resulting generation is:
public static readonly global::System.Windows.DependencyProperty TestPropProperty =
global::System.Windows.DependencyProperty.RegisterAttached(
name: "TestProp",
propertyType: typeof(global::MyNamespace.Test),
ownerType: typeof(global::MyNamespace.Test),
defaultMetadata: new global::System.Windows.FrameworkPropertyMetadata(
defaultValue: default(global::MyNamespace.Test),
flags: global::System.Windows.FrameworkPropertyMetadataOptions.None,
propertyChangedCallback: null,
coerceValueCallback: null,
isAnimationProhibited: false),
validateValueCallback: null);
TestChanged call needs to be generated
public static readonly global::System.Windows.DependencyProperty TestPropProperty =
global::System.Windows.DependencyProperty.RegisterAttached(
name: "TestProp",
propertyType: typeof(global::MyNamespace.Test),
ownerType: typeof(global::MyNamespace.Test),
defaultMetadata: new global::System.Windows.FrameworkPropertyMetadata(
defaultValue: default(global::MyNamespace.Test),
flags: global::System.Windows.FrameworkPropertyMetadataOptions.None,
propertyChangedCallback: static (sender, args) =>
{
TestChanged(
(global::System.Windows.FrameworkElement)sender,
(Test?)args.NewValue);
},
coerceValueCallback: null,
isAnimationProhibited: false),
validateValueCallback: null);
No response
1.1.4
Visual Studio 2022-preview
Real life example: https://stackoverflow.com/a/31835729/6461844
Previously discussed in #2
Advantages in comparison to the current approach:
partial
keyword, hence smoother transitionvirtual
Possible disadvantage: slower code generation, but should not be slower than CommunityToolkit/dotnet#8 code generator.
Optionally consider adding an OnChanged
property to the attributes which would specify the method to be called: OnChanged = nameof(NonStandardPropertyChanged)
. This is the equivalent of CanExecute
property in the [RelayCommand]
attribute in CommunityToolkit.Mvvm
library.
After updating to version 1.4.0 I got the error "Namespace 'DependencyPropertyGenerator'" not found for TargetFramework "net472".
net6.0-windows is compiled correctly, but net472 gets error.
Expected behaviour: Compilation works.
No response
1.4.0
Visual Studio 2022
No response
The Generic weak event manager is now used for all weak events in WPF. Ideally, we need to define cases where it is possible to use optimized specialized event managers.
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/events/weak-event-patterns?view=netdesktop-6.0#how-to-implement-the-weak-event-pattern
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.