Page 1 of 1

DependencyProperty.AddOwner registers multiple callbacks for single type

Posted: 08 Dec 2022, 11:57
by daniilch
Hello. I think, I found a bug in DependencyProperty.AddOwner implementation.

Lets create two UserControls: UserControlA and UserControlB.
UserControlA defines a dependency property Value with a default value and a change callback.
UserControlB reuses this property with AddOwner, redefining its own change callback.

Code:
public partial class UserControlA : UserControl
{
    ... ctor, InitializeComponent, CLR property definition omitted ... 

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(int), typeof(UserControlA), new PropertyMetadata(5, OnValueChanged));

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine($"UserControlA: d is {d.GetType().Name}: Value changed to {e.NewValue}");
    }
}

public partial class UserControlB : UserControl
{
    ... ctor, InitializeComponent, CLR property definition omitted ... 

    public static readonly DependencyProperty ValueProperty =
        UserControlA.ValueProperty.AddOwner(typeof(UserControlB), new PropertyMetadata(OnValueChanged));

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine($"UserControlB: d is {d.GetType().Name}, Value changed to {e.NewValue}");
    }
}
Lets use these controls somewhere in a view in the following way:
<StackPanel Orientation="Vertical">
    <vcviews:UserControlA Value="8" />
    <vcviews:UserControlB Value="10" />
</StackPanel>
Compiling and runnig this code in WPF we get the following messages in output window:
UserControlA: d is UserControlA: Value changed to 8
UserControlB: d is UserControlB, Value changed to 10
All is fine, both controls got their change notifications.

But in Noesis this code fails with exception:
ArgumentException: Invalid default value type for dependency property 'Brio.MRS.ViewCore.Views.UserControlB.Value'
Noesis.DependencyProperty.ValidateDefaultValue (System.String name, System.Type type, System.Type owner, System.Object value) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Proxies/DependencyPropertyExtend.cs:180)
Noesis.DependencyProperty.AddOwner (System.Type ownerType, Noesis.PropertyMetadata metadata) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Proxies/DependencyPropertyExtend.cs:42)
Brio.MRS.ViewCore.Views.UserControlB..cctor () (at Assets/Modules/ViewCore/Views/UserControlB.xaml.cs:12)
Rethrow as TypeInitializationException: The type initializer for 'Brio.MRS.ViewCore.Views.UserControlB' threw an exception.
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (System.RuntimeTypeHandle type) (at <695d1cc93cca45069c528c15c9fdd749>:0)
Noesis.Extend.RunClassConstructor (System.Type type) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Extend.cs:1765)
Noesis.Extend.RegisterDependencyProperties (System.Type type) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Extend.cs:1730)
Noesis.Extend.RegisterNativeType (System.Type type, System.Boolean registerDP) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Extend.cs:1374)
Noesis.Extend.RegisterNativeType (System.Type type) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Extend.cs:1221)
Noesis.Extend.RegisterType (System.String typeName) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Extend.cs:1877)
UnityEngine.Debug:LogException(Exception)
NoesisUnity:OnUnhandledException(Exception) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/NoesisUnity.cs:374)
Noesis.Error:UnhandledException(Exception) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Error.cs:18)
Noesis.Extend:RegisterType(String) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/Extend.cs:1882)
Noesis.GUI:Noesis_LoadComponent(HandleRef, String)
Noesis.GUI:LoadComponent(Object, String) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/API/Core/NoesisGUI.cs:322)
NoesisUnity:LoadComponent(Object, String) (at Library/PackageCache/com.noesis.noesisgui@36e5d70d8b/Runtime/NoesisUnity.cs:270)
Brio.MRS.BimViewer.Views.BimViewerView:InitializeComponent() (at Assets/Modules/BimViewer/Views/BimViewerView.xaml.cs:20)
Brio.MRS.BimViewer.Views.BimViewerView:.ctor() (at Assets/Modules/BimViewer/Views/BimViewerView.xaml.cs:14)
...
Adding a default value to UserControlB property definition:
public partial class UserControlB : UserControl
{
    public static readonly DependencyProperty ValueProperty =
        UserControlA.ValueProperty.AddOwner(typeof(UserControlB), new PropertyMetadata(7, OnValueChanged));
                                                                               //------^
    ...
}
After that exception does not occure, but there's another problem: UserControlA receives property change callback from UserControlB:
UserControlA: d is UserControlA: Value changed to 8
UserControlA: d is UserControlB: Value changed to 10    <== !    
UserControlB: d is UserControlB, Value changed to 10
Of course, there's no actual need to use AddOwner in this code (and in my code too, to be fair), but this is a behaviour mismatch between WPF and Noesis, and you guys seem to be willing to fix those things :) Thanks in advance.

Re: DependencyProperty.AddOwner registers multiple callbacks for single type

Posted: 12 Dec 2022, 18:45
by sfernandez
Hi,

There are clearly a couple of problems here, first we should allow not specifying the default value when doing AddOwner, and then the multiple callbacks error. Could you please report them in our bugtracker? we will solve them as soon as possible.

Re: DependencyProperty.AddOwner registers multiple callbacks for single type

Posted: 13 Dec 2022, 06:59
by daniilch
Sure, I filed a bug: https://www.noesisengine.com/bugs/view.php?id=2476

By the way if I find a bug is it better to create a forum post beforehand, or maybe I may create an issue in bugtracker directly?

Re: DependencyProperty.AddOwner registers multiple callbacks for single type

Posted: 16 Dec 2022, 18:24
by sfernandez
Thanks for the report.

For crashes it is better to open a ticket in the bugtracker with a crash dump if possible, and reproduction steps.
But if you're unsure if something that is happening to you is a missing feature, usage error or something wrong in Noesis, don't hesitate to ask in the forums.