【问题标题】:How to access entire ViewModel from within a Command Object如何从命令对象中访问整个 ViewModel
【发布时间】:2013-11-20 16:16:03
【问题描述】:

基于@stuart 的blog post,我可以看到如何将文字字符串绑定为CommandParameter。

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
    }
}

当命令位于它自己的命令对象而不是 ViewModel 中时,如何将整个 ViewModel 绑定为按钮的 CommandParameter?

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

注意:如果我必须以某种方式扩展 MvvmCross 以使此功能以类似于 WPF 的统一方式实现,我可以接受。我只是不知道从哪里开始。强>


我找到的所有示例都直接在 ViewModel 中声明命令,如下所示:

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}"/>

ViewModel 命令属性:

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() );
    }
}

【问题讨论】:

    标签: c# android xamarin model-binding mvvmcross


    【解决方案1】:

    默认情况下,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; }
    }
    

    使用它,您可以在 axml 中使用 MyButton 而不是 Button

     <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

    【讨论】:

    • 使用local:MvxBind="Click FindUserCommand, CommandParameter=ViewModel我可以看到Execute (parameter)参数值==“ViewModel”。我怎样才能让它真正成为整个 ViewModel 对象?
    • 我一直在研究这个自定义按钮位,但它对我来说并没有组合在一起。我已经更新了问题并添加了赏金。如果你有兴趣...
    • 太棒了,这条线为我做了Command SearchCommand;CommandParameter . 作为后续,是否可以根据命令的“CanExecute”状态启用/禁用按钮?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多