Page 1 of 2

Unity: Do DependencyProperties / Control.SetBinding work?

Posted: 22 Feb 2015, 04:27
by co_nl_on
Can I make dependency properties for my UserControls and use them like I would in WPF? I'm attempting this but I get the error:
Exception: Unknown Unity extended type
Noesis.Error.Check () (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisError.cs:21)
Noesis.DependencyProperty.Noesis_RegisterDependencyProperty_String_ (IntPtr classType, IntPtr propertyName, IntPtr propertyMetadata) (at Assets/Plugins/NoesisGUI/Scripts/Proxies/DependencyPropertyExtend.cs:262)
Noesis.DependencyProperty.Register (System.String propertyName, System.Type propertyType, System.Type ownerType, Noesis.PropertyMetadata propertyMetadata) (at Assets/Plugins/NoesisGUI/Scripts/Proxies/DependencyPropertyExtend.cs:155)
Controls.GringosIcon..cctor ()
Rethrow as TypeInitializationException: An exception was thrown by the type initializer for Controls.GringosIcon

Here are the relevant bits of my code

GringosIcon.xaml
<UserControl x:Class="Controls.GringosIcon"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  UseLayoutRounding="True">
        <Button
        x:Name="Button">
            <Border
            BorderThickness="4"
            BorderBrush="{Binding Path=FrameBrush, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
                <!-- Button Content -->
            </Border>
        </Button>
</UserControl>
 
GringosIcon.xaml
    public enum IconState
    {
        Targetable,
        Active,
        NotTargetable,
        Inactive,
        Selected,
    }

    [Noesis.UserControlSource(@"Assets/Gringos/xamls/Controls/GringosIcon.xaml")]
    public class GringosIcon : Noesis.UserControl, INotifyPropertyChanged
    {
        public static readonly DependencyProperty PropertyTypeProperty = DependencyProperty.Register(
            "DpIconState", typeof (IconState), typeof (GringosIcon), new PropertyMetadata(default(IconState)));

        public IconState DpIconState
        {
            get { return (IconState) GetValue(PropertyTypeProperty); }
            set
            {
                SetValue(PropertyTypeProperty, value);
                OnPropertyChanged("FrameBrush");
            }
        }

        public Brush FrameBrush
        {
            get
            {
                switch (DpIconState)
                {
                    // bla bla bla
                }
            }
        }
 
And lastly GringosIconController (which is a MonoBehavior)
public class GringosIconController : EventBehaviour, INotifyPropertyChanged
{
    public GringosIcon controlledIcon;

    public IconState DpIconState
    {
        get
        {
                if (TargetMode)
                {
                    if (gameObject.Equals(CurrentTargeter))
                    {
                        return IconState.Selected;
                    }

                    return CanBeTargeted ? IconState.Targetable : IconState.NotTargetable;
                }
                return IconActive ? IconState.Active : IconState.Inactive;
        }
    }

    // other stuff

    void Start()
    {
        controlledIcon.DataContext = this;
        controlledIcon.SetBinding(GringosIcon.PropertyTypeProperty, "DpIconState");
       // other stuff
    }

    // other stuff
}
 
I suspect that the problem is that I have not given one of these classes the [Noesis.Extend] attribute. But that attribute has been removed. I thought I could use INotifyPropertyChanged instead? Can you explain why this isn't working?

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 22 Feb 2015, 09:25
by co_nl_on
OK tried to repro with a simpler type. Apparently you can't have readonly DependencyProperties with NoesisGUI.

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 22 Feb 2015, 15:07
by jsantos
There is a problem with using readonly and the way we connect Dependency Properties in mono. But you should be getting a clear error about it, thing that is not happening in your sample. Could you please file a bug?

Once you remove the readonly, does your code works as you expected?

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 22 Feb 2015, 20:26
by co_nl_on
I tried to repro yesterday with 1.2RC2 but then it actually worked. Today I'm going to see if it works now.

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 22 Feb 2015, 22:59
by co_nl_on
Still getting the same error. Let me continue investigating. In a different project it worked just fine :cry:

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 23 Feb 2015, 00:30
by co_nl_on
BINGO found the bug. If a UserControl has a dependency property, it throws this exception (and crashes the Unity Editor) if it's first initialized via C# code. If the first initialization happens in XAML then everything works fine. The work around for this is easy now that I know it.

Check your static initializer and make sure it works regardless of whether C# or the Gui Engine is calling it.

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 23 Feb 2015, 00:46
by jsantos
Thanks a lot for helping with this!

One question, what do you exactly mean with "first initialized" ?

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 23 Feb 2015, 01:49
by co_nl_on
By initialize I mean call the constructor, and the first time you call the constructor you also call the static constructor.

If I have a UserControl called FooButton, and if I include it in the XAML like this

<local: Foobuton ... />

Then the first time I construct an object of that type will be in the XAML, but if I don't have it in the XAML and instead add it like this

var fooButton = new FooButton();

Then it's first constructed with the code. This only seems to matter if FooButton also has a DependencyProperty (which gets set up by the static constructor)

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 24 Feb 2015, 11:55
by sfernandez
Can I make dependency properties for my UserControls and use them like I would in WPF? I'm attempting this but I get the error:
Exception: Unknown Unity extended type
...
In 1.1 version, only DependencyProperties of BaseComponent type (as long as basic types: string, float, bool, ...) can be defined. This normally isn't a problem because we only support to extend classes inheriting from BaseComponent in that version, so you can just define the property as BaseComponent type.

But if you are using 1.2 beta version, we just released RC2 which solves this limitation, and you should be able to register DependencyProperties of any type. If you find any problems registering your property in that version, please file a ticket in our bugtracker and we will fix it as soon as possible ;)

Re: Unity: Do DependencyProperties / Control.SetBinding work

Posted: 24 Feb 2015, 18:50
by jsantos
Then the first time I construct an object of that type will be in the XAML, but if I don't have it in the XAML and instead add it like this

var fooButton = new FooButton();
Hmmm, one question, are you creating this FooButton before NoesisGUI is initialized or even in editor mode (out of PlayMode?) because those are scenarios we do not support right now (although we should assert properly).