UI action in middle of MvxCommand

▼魔方 西西 提交于 2019-11-28 01:23:58

问题


I am using MvvmCross, but this may be general command binding.

When user click a button, the application require an extra input data before proceed to what I want to do in the actual command. The problem that I cannot call an UI action in middle of ViewModel, so just binding MvxCommand (or any ICommand) would not work.

One may ask why: 1) I don't put an input on the UI and user can enter data before click button -> I don't have space. 2) Make default data, and let user change it later -> This my first though, but user tend to forget to change it later!!

So can someone come up with a solution? The only thing I can think of is forgetting command binding, and have code behind pop the ui for extra data, then call a method in view model!

Thanks


回答1:


There are several ways to do this.

My personal preferred way is to use an "Interaction Request" - something that I learnt from the Prism framework from Microsoft patterns and practices.

In Mvx, you can do this using an IMvxInteraction property on your ViewModel. An example of this is shown in https://github.com/slodge/BindingTalk/blob/master/BindingTalk.Core/ViewModels/QuestionViewModel.cs

Each time an interaction is requested, the ViewModel provides an object to the View - in this case a YesNoQuestion:

public class YesNoQuestion
{
    public Action YesAction { get; set; }
    public Action NoAction { get; set; }
    public string QuestionText { get; set; }

    public YesNoQuestion()
    {
        YesAction = () => { };
        NoAction = () => { };
    }
}

The ViewModel exposes the requester using an IMvxInteraction<TQuestion> property:

public class QuestionViewModel
    : MvxViewModel
{
    private MvxInteraction<YesNoQuestion> _confirm = new MvxInteraction<YesNoQuestion>();
    public IMvxInteraction<YesNoQuestion> Confirm
    {
        get { return _confirm; }
    }

    public IMvxCommand GoCommand
    {
        get
        {
            return new MvxCommand(() =>
                {
                    var question = new YesNoQuestion()
                        {
                            QuestionText = "Close me now?",
                            YesAction = () => Close(this),
                        };
                    _confirm.Raise(question);
                });
        }
    }
}

The view on each platform can then bind and subscribe to the interaction request property. This is a little fiddly - because it uses weak references to prevent memory leaks - especially on iOS, but also possible on other platforms too.

Some example Droid code for this is in:

  • https://github.com/slodge/BindingTalk/blob/master/BindingTalk.Droid/Views/2%20%20More%20Controls/QuestionView.cs
  • with AXML in https://github.com/slodge/BindingTalk/blob/master/BindingTalk.Droid/Resources/Layout/QuestionView.axml

Sorry for the confusing ConfirmationView and QuestionView names here - the first is an Android View, the second is an Mvvm View and an Android Activity.

Also, please note that when implementing Dialogs in Android, then you need to be careful about screen rotation - as Android's Activity lifecycle can very much confuse things here - easiest mecahnism (I find) is to just handle screen rotation yourself rather than allowing Android to handle it.



来源:https://stackoverflow.com/questions/22639808/ui-action-in-middle-of-mvxcommand

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!