2

I have simple WPF application with two windows and I want to change it to use the MVVM model.

I started creating a simple binding with a button and a messagebox, but it doesn't work. The Execute function of my command is never called, but I get no binding error in the output window.

I debug and trace the binding using these: http://www.beacosta.com/blog/?p=52 How to detect broken WPF Data binding?

The trace is the following:

System.Windows.Data Warning: 54 : Created BindingExpression (hash=8493835) for Binding (hash=45202970)
System.Windows.Data Warning: 56 :   Path: 'LoginCommand'
System.Windows.Data Warning: 58 : BindingExpression (hash=8493835): Default mode resolved to OneWay
System.Windows.Data Warning: 59 : BindingExpression (hash=8493835): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 60 : BindingExpression (hash=8493835): Attach to System.Windows.Controls.Button.Command (hash=17604022)
System.Windows.Data Warning: 65 : BindingExpression (hash=8493835): Resolving source 
System.Windows.Data Warning: 68 : BindingExpression (hash=8493835): Found data context element: Button (hash=17604022) (OK)
System.Windows.Data Warning: 76 : BindingExpression (hash=8493835): Activate with root item LoginViewModel (hash=47369058)
System.Windows.Data Warning: 106 : BindingExpression (hash=8493835):   At level 0 - for LoginViewModel.LoginCommand found accessor ReflectPropertyDescriptor(LoginCommand)
System.Windows.Data Warning: 102 : BindingExpression (hash=8493835): Replace item at level 0 with LoginViewModel (hash=47369058), using accessor ReflectPropertyDescriptor(LoginCommand)
System.Windows.Data Warning: 99 : BindingExpression (hash=8493835): GetValue at level 0 from LoginViewModel (hash=47369058) using ReflectPropertyDescriptor(LoginCommand): RelayCommand (hash=32714449)
System.Windows.Data Warning: 78 : BindingExpression (hash=8493835): TransferValue - got raw value RelayCommand (hash=32714449)
System.Windows.Data Warning: 82 : BindingExpression (hash=8493835): TransferValue - implicit converter produced <null>
System.Windows.Data Warning: 87 : BindingExpression (hash=8493835): TransferValue - using final value <null>

The relevant parts of my code are below.

Loginview.xaml:

<Window.DataContext>
    <local:LoginViewModel/>
</Window.DataContext>

...

<Button Content="Login"
        Command="{Binding LoginCommand, diagnostics:PresentationTraceSources.TraceLevel=High}"
        CommandParameter="Hello">

LoginViewModel.cs:

class LoginViewModel
{
    private RelayCommand m_LoginCommand;
    public RelayCommand LoginCommand
    {
        get
        {
            if (m_LoginCommand == null) 
            {
                m_LoginCommand = new RelayCommand(param => this.Login(param));
            }
            return m_LoginCommand;
        }
    }

    public void Login(object obj)
    {
        MessageBox.Show(obj.ToString());
    }
}

RelayCommand.cs:

class RelayCommand
{
    private Action<object> _execute;

    public RelayCommand(Action<object> execute)
    {
        _execute = execute;
    }

    #region ICommand Members

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

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        // breakpoint; code execution never reaches here
        _execute(parameter);
    }

    #endregion
}
Community
  • 1
  • 1
hthms
  • 853
  • 1
  • 10
  • 25
  • I assume all your classes are "public" in your code? – sa_ddam213 Dec 01 '12 at 11:46
  • Nope... they have the default visibility. I've tried this tutorial (http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute) in a different project and it works. – hthms Dec 01 '12 at 11:55
  • Is this the actual code? It won't compile, this line is wrong: MessageBox.Show(obj.ToString()); – dzavala Dec 01 '12 at 12:43

1 Answers1

2

Your RelayCommand is a plain class, it is not implementing ICommand. This will work:

class RelayCommand : ICommand
{
    private Action<object> _execute;

    public RelayCommand(Action<object> execute)
    {
        _execute = execute;
    }

    #region ICommand Members

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

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        // breakpoint; code execution never reaches here
        _execute(parameter);
    }

    #endregion
}
dzavala
  • 988
  • 10
  • 21
  • Yes, this was the problem! Thanks, such a lame error! What I still don't get however are the trace messages... TransferValue - implicit converter produced is so meaningless. – hthms Dec 01 '12 at 12:53