Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
564 views
in Technique[技术] by (71.8m points)

user interface - UI action in middle of MvxCommand

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...