lomoonmoonbird
Topic Author
Posts: 30
Joined: 15 Mar 2016, 04:41

no Constructor found for Commands using MVVM

29 Mar 2016, 05:12

Hi
I have five files under the same directory in the Assets named mvvmtest (Assets/mvvmtest/ these five files),which are BaseViewModel,FirstModel(role Model),FirstViewModel(role ViewModel),FirstWindow(role View),RelayCommand,to implement MVVM pattern,but there always an error occurring all the time,but if i put FirstViewModel,FirstModel,RelayCommand,BaseViewModel in one file ,like it did http://www.noesisengine.com/docs/Gui.Co ... orial.html, it will work,but when i separate it into modules, although the namespace is correctly referenced,but this error always shows:
MissingMethodException: No constructor found for Presentation.Conmmands.RelayCommand::.ctor()
System.Activator.CreateInstance (System.Type type, BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Activator.cs:319)
System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Activator.cs:268)
System.Activator.CreateInstance (System.Type type, System.Object[] args) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Activator.cs:263)
Noesis.Extend.CreateInstance (IntPtr unityType, IntPtr cPtr) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisExtend.cs:3855)
UnityEngine.Debug:LogException(Exception)
Noesis.Debug:LogException(Exception) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisDebug.cs:24)
Noesis.Error:SetNativePendingError(Exception) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisError.cs:33)
Noesis.Extend:CreateInstance(IntPtr, IntPtr) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisExtend.cs:3875)
System.Object:wrapper_native_000007FED33F9690(String)
NoesisGUISystem:Noesis_LoadXAML(String) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisGUISystem.cs:405)
NoesisGUISystem:Load(String) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisGUISystem.cs:279)
NoesisGUISystem:LoadXaml(String) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisGUISystem.cs:47)
NoesisGUIPanel:LoadXaml() (at Assets/Plugins/NoesisGUI/Scripts/NoesisGUIPanel.cs:496)
NoesisGUIPanel:OnEnable() (at Assets/Plugins/NoesisGUI/Scripts/NoesisGUIPanel.cs:383)

NoesisException: Loading Assets/mvvmtest/FirstWindow.xaml
No constructor found for Presentation.Conmmands.RelayCommand::.ctor()
Noesis.Error.Check () (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisError.cs:26)
NoesisGUISystem.Noesis_LoadXAML (System.String xamlFile) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisGUISystem.cs:406)
NoesisGUISystem.Load (System.String xamlFile) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisGUISystem.cs:279)
NoesisGUISystem.LoadXaml (System.String xamlFile) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisGUISystem.cs:47)
NoesisGUIPanel.LoadXaml () (at Assets/Plugins/NoesisGUI/Scripts/NoesisGUIPanel.cs:496)
NoesisGUIPanel.OnEnable () (at Assets/Plugins/NoesisGUI/Scripts/NoesisGUIPanel.cs:383)


These are my implementation:

FirstModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Presentation.Models
{
    class FirstModel 
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }

        public string ToUpper()
        {
            return this._name.ToUpper();
        }

        public bool isValid()
        {
            return true;
        }

    }
}

BaseViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ComponentModel;

namespace Presentation.ViewModels1
{
    class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisedPropertyChanged(string prop)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(prop));
            }
        }
    }
}

FirstViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Presentation.Models;
using Presentation.Conmmands;
using Presentation.ViewModels1;
namespace Presentation.ViewModels
{
    
    class FirstViewModel : BaseViewModel
    {
        FirstModel fm;

        public Presentation.Conmmands.RelayCommand Button1ToUpperCommand
        {
            get; set;
        }
        public FirstViewModel()
        {
            Console.WriteLine("firstviewmodel initial aaaaaaaaaaaaaaaa");
            fm = new FirstModel();
            fm.Name = "bakerl";
            Button1ToUpperCommand = new Presentation.Conmmands.RelayCommand(ToUpper);
            Console.WriteLine(Button1ToUpperCommand);
        }
       
        public string textbox1
        {
            get
            {
                
                return fm.Name;

            }
            set
            {
                
                if (fm.Name != value)
                {
                    Console.WriteLine("-------");
                    fm.Name = value;
                    RaisedPropertyChanged("textbox1");
                }
                
            }
        }

        public void ToUpper(object parameter)
        {
            string a = fm.ToUpper();
            textbox1 += a;
            //fm.Name += textbox1;
            Console.WriteLine(a);
        }
    }
}


RelayCommand:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace Presentation.Conmmands
{
    class RelayCommand : ICommand
    {
        private readonly Action<object> _action;

        public RelayCommand(Action<object> action)
        {
            _action = action;
        }

        public event EventHandler CanExecuteChanged
        {
            add { }
            remove { }
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            _action(parameter);
        }

    }

}



FirstWindow.xaml:

<Grid 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:vm="clr-namespace:Presentation.ViewModels"
        mc:Ignorable="d"
        Height="300" Width="300"
        DataContext="{DynamicResource FirstViewModel}">
    <Grid.Resources>
        <vm:FirstViewModel x:Key="FirstViewModel"></vm:FirstViewModel>
    </Grid.Resources>
    <Grid>
        <StackPanel>
            <TextBox Name="textbox1" Text="{Binding textbox1, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBlock Text="{Binding Text, ElementName=textbox1}"></TextBlock>
            <Button Name="button1" Content="convert" Command="{Binding Path=Button1ToUpperCommand}"></Button>
            <TextBlock Text="{Binding textbox1}"></TextBlock>
        </StackPanel>
        
    </Grid>
</Grid>

Any idears ? Thanks in advance.
 
User avatar
jsantos
Site Admin
Posts: 2902
Joined: 20 Jan 2012, 17:18
Contact:

Re: no Constructor found for Commands using MVVM

29 Mar 2016, 18:18

The fact that you have RelayCommand in a public setter like this:
public Presentation.Conmmands.RelayCommand Button1ToUpperCommand
{
    get; set;
}
Forces you to have a default public ctor in RelayCommand() (or having the setter private with { get; private set; }). This is a limitation of our current architecture that will be solved in 1.3, in that version serialization is going to be eliminated. Another alternative is setting the data context by code, this is the recommended option because you don't pollute the XAML with codebehind classes, making the XAML more portable.

Are you sure it worked whenever you had all the classes in a single file?
 
lomoonmoonbird
Topic Author
Posts: 30
Joined: 15 Mar 2016, 04:41

Re: no Constructor found for Commands using MVVM

30 Mar 2016, 13:08

Hi

I changed
public Presentation.Conmmands.RelayCommand Button1ToUpperCommand
{
    get; set;
}
to
public Presentation.Conmmands.RelayCommand Button1ToUpperCommand
{
    get; private set;
}
but the same error.

And it did work when i put these files into one file.
 
User avatar
jsantos
Site Admin
Posts: 2902
Joined: 20 Jan 2012, 17:18
Contact:

Re: no Constructor found for Commands using MVVM

30 Mar 2016, 13:34

Does it work if you add a default ctor to RelayCommand? The solution is not very important because, as said, this is going to change in v1.3
 
lomoonmoonbird
Topic Author
Posts: 30
Joined: 15 Mar 2016, 04:41

Re: no Constructor found for Commands using MVVM

30 Mar 2016, 14:11

Hi
I dont know about ctor,can you specify more about how to do it according to my codes above, thanks.
 
User avatar
jsantos
Site Admin
Posts: 2902
Joined: 20 Jan 2012, 17:18
Contact:

Re: no Constructor found for Commands using MVVM

30 Mar 2016, 17:30

Sorry for my bad explanation. A default constructor, something like this
class RelayCommand : ICommand
{
    private readonly Action<object> _action;

    public RelayCommand() {}

    public RelayCommand(Action<object> action)
    {
        _action = action;
     }
...
 
lomoonmoonbird
Topic Author
Posts: 30
Joined: 15 Mar 2016, 04:41

Re: no Constructor found for Commands using MVVM

31 Mar 2016, 03:56

Hi
This method i had used before, it also thrown error when click the button
NullReferenceException: Object reference not set to an instance of an object
Presentation.Conmmands.RelayCommand.Execute (System.Object parameter) (at Assets/mvvmtest/RelayCommand.cs:35)
Noesis.Extend.CommandExecute (IntPtr cPtr, IntPtr paramPtr) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisExtend.cs:1545)
UnityEngine.Debug:LogException(Exception)
Noesis.Debug:LogException(Exception) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisDebug.cs:24)
Noesis.Error:SetNativePendingError(Exception) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisError.cs:33)
Noesis.Extend:CommandExecute(IntPtr, IntPtr) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisExtend.cs:1549)
System.Object:wrapper_native_000007FEE4E89810(Int32, Single, Single, Int32)
Noesis.UIRenderer:Noesis_MouseButtonUp(Int32, Single, Single, Int32) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisUIRendererImports.cs:215)
Noesis.UIRenderer:ProcessEvent(Event, Boolean, Boolean) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisUIRenderer.cs:436)
NoesisGUIPanel:OnGUI() (at Assets/Plugins/NoesisGUI/Scripts/NoesisGUIPanel.cs:456)

NoesisException: Object reference not set to an instance of an object
Noesis.Error.Check () (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisError.cs:26)
Noesis.UIRenderer.Noesis_MouseButtonUp (Int32 rendererId, Single x, Single y, Int32 button) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisUIRendererImports.cs:216)
Noesis.UIRenderer.ProcessEvent (UnityEngine.Event ev, Boolean enableKeyboard, Boolean enableMouse) (at Assets/Plugins/NoesisGUI/Scripts/Core/NoesisUIRenderer.cs:436)
NoesisGUIPanel.OnGUI () (at Assets/Plugins/NoesisGUI/Scripts/NoesisGUIPanel.cs:456)
 
User avatar
jsantos
Site Admin
Posts: 2902
Joined: 20 Jan 2012, 17:18
Contact:

Re: no Constructor found for Commands using MVVM

01 Apr 2016, 01:16

Inspecting your XAML, I see one thing that is wrong. The Command syntax is not correct (you must not use the Path keyword).
<Button Name="button1" Content="convert" Command="{Binding Path=Button1ToUpperCommand}"></Button>
It should be
<Button Name="button1" Content="convert" Command="{Binding Button1ToUpperCommand}"></Button>
 
lomoonmoonbird
Topic Author
Posts: 30
Joined: 15 Mar 2016, 04:41

Re: no Constructor found for Commands using MVVM

01 Apr 2016, 04:58

Hi

I think its not the Path problem,i created a new unity project , and dragged these files in the folder as same as i did above,i had the Path property in Command binding, and i also didn't have default constructor for RelayCommand, then it worked without any error,strange behaviour,anyway ,Thanks,i think this problem should be tagged with solved. :) Thanks again.
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: no Constructor found for Commands using MVVM

06 Apr 2016, 10:40

Hi,

I replicated your scenario using the latest NoesisGUI 1.2.5f11 and it behaves the same no matter I use several files or a unique file. It always complains about RelayCommand no having a default ctor when playing, because it is serialized into the XAML.

If I change the Button1ToUpperCommand property in FirstViewModel to:
public Presentation.Conmmands.RelayCommand Button1ToUpperCommand
{
    get;
    private set;
} 
And modify the XAML so it's rebuilt again with the new class definitions (this step is important because otherwise the RelayCommand is still serialized into the file), then I can play your example without problems. I think this last step was the one you missed and why you still got errors.

I hope this helps.

Who is online

Users browsing this forum: jsantos and 1 guest