Reputation: 1925
I have a very simple application that rely on MVVMCross + Xamarin Android.
I have been able to create a WP8 application LoginView (Username + Password + Submit Button) that bind to a Cmd with parameter(which will be my password) in the ViewModel . Now I try to do the same with Android . How to express the CommandParameter(which is another field of the view) in the axml file for my LoginView?
public class LoginViewModel : MvxViewModel
{
private readonly ILoginService _loginService;
public LoginViewModel(ILoginService loginService)
{
_loginService = loginService;
}
private string _username;
public string Username
{
get { return _username; }
set { _username = value; RaisePropertyChanged(() => Username); }
}
private string _error;
public string Error {
get { return _error; }
set { _error = value; RaisePropertyChanged(() => Error); }
}
#region LoginCmd
private MvxCommand<string> _loginCmd;
public ICommand LoginCmd
{
get
{
_loginCmd = _loginCmd ?? new MvxCommand<string>(DoLoginCmd);
return _loginCmd;
}
}
private void DoLoginCmd(string password)
{
try
{
_loginService.Login(Username, password);
ShowViewModel<ProjectsListViewModel>();
}
catch (SecurityException ex)
{
Error = ex.Message;
}
}
#endregion
}
Upvotes: 2
Views: 2668
Reputation: 66882
For general commandparameter binding see Using MvxCommand With CommandParameter binding
For binding to a value within the View, my general answer is don't
MvvmCross doesn't support ElementName or RelativeSource type binding source.
Instead all bindings are to the ViewModel/DataContext
For your app example, you could easily bind the Password to a property in your ViewModel - just like you do with UserName
Update after comments discussion.
If Password
is a special case because of Xaml security concerns, then some options you could try are:
you could work around those security concerns using AttachedProperties - see links like http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html for details
you could bind the Password
property on Android and iOS and then use the Tibet binding syntax to bind the Click event with a ViewModel bound CommandParameter - something like Click CommandParameter(LoginCmd, Password)
you could use ViewModel based-logic to use either the parameter-passed-in Password or (when null) the ViewModel Password property (password = password ?? Password;
)
you could use code-behind or custom control binding tricks to make the command parameter work... e.g. you could:
SetPasswordEditText(EditText text)
method to LoginButtonPasswordClick
ICommand property to LoginButton and cause it to fire.
public class LoginButton : Button
{
public LoginButton(Context c, IAttributeSet a) : base(c,a) {
this.Click += (s,e) => {
if (LoginClick == null) return;
if (PasswordEditText == null) return;
if (LoginClick.CanExecute(PasswordEditText.Text))
LoginClick.Execute(PasswordEditText.Text);
}
}
public ICommand LoginClick {get;set;}
public EditText PasswordEditText {get;set;}
}
// codebehind in OnCreate as:
var l = FindViewById<LoginButton>(Resource.Id.the_login_button);
var p = FindViewById<EditText>(Resource.Id.the_password_box);
l.PasswordEditText = p;
// Axml is:
<LoginButton
local:MvxBind="LoginClick LoginCmd"
android:... etc />
Upvotes: 4