Executing UI Code from ViewModel on MVVMCross

后端 未结 2 1682
北荒
北荒 2020-12-14 13:27

I have just started using MvvmCross, but i didn\'t find any info about to how i can execute UI code from a ViewModel.

On Caliburn there are coroutine so i can acces

相关标签:
2条回答
  • 2020-12-14 13:50

    There exists an easier way. Here is the method I use for executing any action on the main thread:

    protected void RunOnUIThread(Action action) {
        var dispatcher = Mvx.Resolve<IMvxMainThreadDispatcher>();
        dispatcher.RequestMainThreadAction(action);
    }
    

    Hope it helps. Cheers.

    0 讨论(0)
  • 2020-12-14 13:55

    There isn't any hard/fast rule on this within MvvmCross.

    Generally, when I need to do this I use the Messenger plugin.

    This answer assumes you are using the latest Alpha v3 code. For older vNext code you'll have to do some translation - see notes below.

    To use this approach:

    I reference Cirrious.MvvmCross.Plugins.Messenger.dll from both Core and UI projects.

    Then I add a line somewhere in Setup.cs (e.g. in InitializeLastChance) to:

    Cirrious.MvvmCross.Plugins.Messenger.PluginLoader.Instance.EnsureLoaded();
    

    Then in the Core project I add a message:

    public class InputIsNeededMessage : MvxMessage
    {
        public InputIsNeededMessage(object sender) : base(sender) {}
    }
    

    In the ViewModel I can get the Messenger by constructor injection or by:

    var messenger = Mvx.Resolve<IMvxMessenger>();
    

    and I can send messages by calling:

    messenger.Publish(new InputIsNeededMessage(this));
    

    In the View I can again get to the messenger and subscribe to messages using:

    var messenger = Mvx.Resolve<IMvxMessenger>();
    _token = messenger.SubscribeOnMainThread<InputIsNeededMessage>(OnInputIsNeeded);
    

    where _token must be a member variable - if it isn't then the subscription won't persist - the subscription itself is weak by default (so you never have to unsubscribe)

    and where OnInputIsNeeded is something like:

    private void OnInputIsNeeded(InputIsNeededMessage message)
    {
        if (message.Sender != ViewModel)
            return;
    
        // do stuff here - you are already on the UI thread
    }
    

    The above sequence is what I normally do for 'proper code'

    To start with using a Messenger/EventAggregator can feel uncomfortable - it certainly took me a while to get used to it - but after I did get used to it, then I now use it everywhere - the pub/sub Message decoupling is very flexible for testing and for future maintenance of code (IMO)

    As alternatives to this approach above I do sometimes take shortcuts:

    • sometimes I fire normal C# events from the ViewModel and have the View respond to these
    • sometimes I have special marker properties and fire the UI code from them

    Sorry for using v3 syntax - but the changeover is coming and it's what I'm now coding in...

    To switch back to vNext I think you might need to:

    • use IMessenger instead of IMvxMessenger
    • use BaseMessage instead of the MvxMessage
    • use Subscribe instead of SubscribeOnMainThread - but then you will need to marshall the message onto the UI thread yourself.
    0 讨论(0)
提交回复
热议问题