2013-11-20 30 views
1

基于@ stuart的blog post,我可以看到如何绑定到一个文字字符串作为CommandParameter。如何从命令对象内访问整个ViewModel

local:MvxBind="Click FindUserCommand, CommandParameter=foo" 
public class FindUserViewModel: ViewModelBase 
{ 
    public FindUserViewModel(IFindUserCommand findUserCommand) 
    { 
     _findUserCommand = findUserCommand; 
    } 

    // class truncated for brevity 

    private IFindUserCommand _findUserCommand; 
    public IFindUserCommand FindUserCommand 
    { 
     get { return _findUserCommand; } 
     set { _findUserCommand = value; RaisePropertyChanged(() = > FindUserCommand); } 
    } 
} 
public class FindUserCommand: IFindUserCommand 
{ 
    // class truncated for brevity 
    public void Execute(object parameter) 
    { 
     // RIGHT HERE: 
     // value of parameter == foo 
    } 
} 

如何绑定整个视图模型作为按钮的CommandParameter当命令居住在它自己的命令对象,而不是视图模型?

public void Execute(object parameter) 
{ 
    var vm = (FindUserViewModel)parameter; 
    var firstName = vm.FirstName; 
    var lastName = vm.LastName; 
    // etc... 
} 

注:如果我必须以某种方式延长MvvmCross作出类似WPF统一的方式这个功能,我确定与..我只是不知道从哪里开始。我


所有例子中找到直接在视图模型声明命令是这样的:

MvvmCross例子

private Cirrious.MvvmCross.ViewModels.MvxCommand _insertCommand; 
public System.Windows.Input.ICommand InsertCommand 
{ 
    get 
    { 
     _insertCommand = _insertCommand ? ? new Cirrious.MvvmCross.ViewModels.MvxCommand(DoInsert); 
     return _insertCommand; 
    } 
} 

private int _countAdded = 0; 

private void DoInsert() 
{ 
    _countAdded++; 
    var kitten = _kittenGenesisService.CreateNewKitten(_countAdded.ToString()); 
    _dataService.Insert(kitten); 
    RefreshDataCount(); 
} 

然后按键绑定到视图这样的:

<Button 
    android:text="Insert" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/button1" 
    local:MvxBind="Click InsertCommand" /> 

但我想在自己的类文件中声明Command对象,以便更易于测试,然后将其注入到ViewModel中。

是否可以在MVVMCross for Android中使用CommandParameter绑定,类似于WPF如何执行其命令参数绑定?


WPF示例:

视图按钮定义:

<Button 
    Command="{Binding SearchCommand}" 
    CommandParameter="{Binding}"/> 

视图模型命令属性:

private ICommand _findUserCommand; 
public ICommand FindUserCommand 
{ 
    get { return _findUserCommand; } 
    set { _findUserCommand = value; RaisePropertyChanged(() => FindUserCommand); } 
} 

命令对象的定义:

public class FindUserCommand : ICommand 
{ 
    private readonly IUserService _userService; 

    public FindUserCommand(IUserService userService) 
    { 
     _userService = userService; 
    } 

    public bool CanExecute (object parameter) 
    { 
     var findUserViewModel = (FindUserViewModel)parameter; 
     return findUserViewModel.NameSearch.Length > 0; 
    } 

    public void Execute (object parameter) 
    { 
     FindUserViewModel.Users = _userService.Find(FindUserViewModel.NameSearch); 
    } 

    public event EventHandler CanExecuteChanged; 
    public void RaiseCanExecuteChanged() 
    { 
     if (CanExecuteChanged != null) 
      CanExecuteChanged(this, new EventArgs()); 
    } 
} 

回答

2

Android小部件(如按钮)默认情况下没有Command和CommandParameter成员 - 因此无法在“开箱即用”时使用它们。

但是,您可以轻松地继承Button以生成MyButton,然后您可以在需要时提供CommandCommandParameter成员。是这样的:使用此

public class MyButton : Button 
{ 
    public MyButton(Context c, IAttributeSet a) : base(c,a) 
    { 
     Click += (s,e) => { 
      if (Command == null) return; 
      if (!Command.CanExecute(CommandParameter)) return; 
      Command.Execute(CommandParameter); 
     }; 
    } 

    public ICommand Command { get;set; } 
    public object CommandParameter { get;set; } 
} 

,你就可以使用MyButton,而不是Button在axml

<MyButton 
    local:MvxBind="Command SearchCommand;CommandParameter ." /> 

更多关于数据绑定看到https://github.com/MvvmCross/MvvmCross/wiki/Databinding


或者,另一种做法是使用基于ValueConverter的方法 - 类似于MvvmCross提供的CommandParameter功能 - 参见http://slodge.blogspot.co.uk/2013/06/commandparameter-binding.html

+0

使用'local:MvxBind =“单击FindUserCommand,CommandParameter = ViewModel'我可以看到'Execute(parameter)'参数值==”ViewModel“。我怎样才能让它成为整个ViewModel对象? –

+0

我一直在寻找这个自定义按钮位,它只是没有为我一起。我已经更新了这个问题并添加了一个赏金。如果你有兴趣... –

+0

太棒了,这一行对我来说是'Command SearchCommand; CommandParameter'。作为后续,是否可以通过命令的“CanExecute”状态来启用/禁用按钮? –