Delegate command not invoked

Topics: Prism v4 - Silverlight 4
Jan 9, 2012 at 10:42 AM

Hi all

I have a silverlight 5 app using prism 4 and am having trouble with delegatecommand.  I have used this feature before in other apps without any trouble but for some reason cannot get it to work in current app.

 This is my login interface

public interface ILoginViewModel
    {
        DelegateCommand<object> LoginCommand { get; set; }
        DelegateCommand<object> CancelLoginCommand { get; set; }
        string Username { get; set; }
        string UserPassword { get; set; }
    }

This is my viewmodel
[Export(typeof(ILoginViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class LoginViewModel : BaseINPC, ILoginViewModel
    {

        #region Private Properties
        private IEventAggregator _eventAggregator;
        private string _username;
        private string _userPassword;
        private IShellDAL _service;
        private string _token;
        #endregion
        
        [ImportingConstructor]
        public LoginViewModel(IEventAggregator eventAggregator)
        {
            this._eventAggregator = eventAggregator;
            _service = new ShellDAL();
            LoginCommand = new DelegateCommand<object>(LoginUser, CanLoginUser);
            //CancelLoginCommand = new DelegateCommand<object>(CancelLogin, CanCancelLogin);
        }


        #region Public properties
        public DelegateCommand<object> LoginCommand { get; set; }
        public DelegateCommand<object> CancelLoginCommand { get; set; }

        public string Username
        {
            get { return _username; }
            set
            {
                _username = value;
                InvokePropertyChanged("Username");
            }
        }

        public string UserPassword
        {
            get { return _userPassword; }
            set
            {
                _userPassword = value;
                InvokePropertyChanged("UserPassword");
            }

        }

        #endregion

        #region Commands
        private bool CanLoginUser(object obj)
        {
            return true; //string.IsNullOrEmpty(Username) && string.IsNullOrEmpty(UserPassword);
        }
        private void LoginUser(object obj)
        {
            if (_service == null)
            {
                _service = new ShellDAL();
            }


            MessageBox.Show("Got this far!");
 
            _service.Login(_username, _userPassword).Subscribe
                (
                    onNext: x =>
                    {
                        _token = x;
                    },
                    onCompleted: () =>
                    {
                        if (!string.IsNullOrEmpty(_token))
                        {
                            var publishLogInEvent = _eventAggregator.GetEvent<LoggedInEvent>();
                            publishLogInEvent.Publish(_token);
                        }
                    }
                );
        }
        #endregion
    }
I'm setting loginCommand in constructor and put a messagebox(had to use messagebox as breakpoints are not been hit but that's another issue) in the LoginUser method that will/should be invoked when button is clicked.

Here's my LoginView.xaml.cs
[Export("LoginView")]
    public partial class LoginView : UserControl
    {
        [Import]
        public ILoginViewModel vm;

        public LoginView()
        {
            InitializeComponent();
            DataContext = vm;
        }
    }

Here's part of the LoginView with the delegate command attached to the button. Not sure what's going on here and have been looking at this to long now so hopefully someone can spot some silly mistake been made.
<Button  Width="80" Content="Login" HorizontalAlignment="Left" cal:Click.Command="{Binding LoginCommand}"/>
Thanks
Paul



Developer
Jan 9, 2012 at 3:34 PM
Edited Jan 9, 2012 at 3:35 PM

Hi,

Based on my understanding, your problem might be related to the fact that the properties retrieved with the [Import] attribute are not populated until after the constructor is completed. Hence your DataContext is set with a null value.

To avoid this you could try using the [ImportingConstructor] attribute, for example like in the following code snippet:

[Export("LoginView")]
    public partial class LoginView : UserControl
    {
        [ImportingConstructor]
        public LoginView(ILoginViewModel vm)
        {
            InitializeComponent();
            DataContext = vm;
        }
    }

I hope you find this helpful,

Agustin Adami
http://blogs.southworks.net/aadami


 

Jan 12, 2012 at 9:58 AM

aadami is right. Are you getting binding errors in your output window? Also why use cal:Click.Command? You can directly bind to the Command property of Button.

Jan 12, 2012 at 10:42 AM
Edited Jan 12, 2012 at 10:50 AM

Thanks all

That worked perfect.

@gan_s, I'm using prism delegate commands.

Ignore above statement

@gan_s

Your correct I can just bind to the Command property of the button.  I have been blindly adding the namespace

xmlns:cal="clr-namespace:Microsoft.Practices.Prism.Commands;assembly=Microsoft.Practices.Prism"

and calling commands using cal:Click.Command.

Not sure how I came to be using this, probably seen it in an old demo?

Anyway thanks to all

Paul