Looking to pop up an alert like displayalert() but from the View Model (Xamarin Forms Labs)

I am using Xamarin Forms Labs and a PCL. I am using the ViewFactory to bind the Views to the View Models. Other than creating a separate alert view and view model, is there a way to get access to that displayalert() method in the Page class?

Best Answers

Answers

  • adamkempadamkemp USInsider, Developer Group Leader mod

    View models are cross-platform, and an alert is a UI thing. You could use an event in your view model and subscribe to that even in your view to trigger the alert to be displayed.

  • AnthonyGaddAnthonyGadd USMember ✭✭

    Thanks for the answer.

    Makes sense, but how do I do that when using the view factory, where the View is only bound to the View Model through the bindings, I don't have access to the View Model object in the View. I am pretty new to IOC and DI so please forgive my noob-ness.

    In App.cs this is all I have that binds the two:

    ViewFactory.Register<Login, LoginVM>();

    return ViewFactory.CreatePage();

  • adamkempadamkemp USInsider, Developer Group Leader mod

    The MessageCenter is also a good suggestion!

  • AnthonyGaddAnthonyGadd USMember ✭✭

    Thanks HiroDev, I am going to go with the MessageCenter. Pretty simple to use.

    Thanks also Adam, I have a feeling I am going to need to do that at some point and I didn't know you could do that. Much appreciated.

  • AllanRitchie-oldAllanRitchie-old CAInsider ✭✭✭

    You can also use the library below. It is available on nuget and allows you to do all sorts of different dialogs from your viewmodels:
    https://github.com/aritchie/acr-xamarin-forms

    with examples on what it does:
    https://github.com/aritchie/acr-xamarin-forms/blob/master/Samples/Samples/ViewModels/UserDialogViewModel.cs

  • LarryXLarryX USMember

    I don't think MessageCenter is a good fit here, for the reason it is a pub/sub and fire and forget pattern, while DisplayAlert is awaitable method call (You need to know what button user clicked before proceed ). You will need a two way messaging to implement this which will be quite cumbersome.

    I think this should be treated similar as INavigation in the sense that Xamarin can put native support for it. Meanwhile, I will define a Interface, and maybe have an attached behavior to has this pushed to ViewModel through one way to source binding.

  • This is how I accomplished this using MessageCenter:

    Page constructor:
    BindingContextChanged += (object sender, EventArgs e) => { MessagingCenter.Send<Page> (this, "BindingContextChanged.MyViewModel"); };

    ViewModel
    Page _page; //... // in constructor MessagingCenter.Subscribe<Page> (this, "BindingContextChanged.MyViewModel", (sender) => { _page = sender; }); //... if(_page != null) { var result = await _page.DisplayAlert("Question?", "Did you see this?", "Yes", "No"); //... }

  • VincentPoirierVincentPoirier CAMember ✭✭

    This threat is the most relevant to my issue, I'm trying to do exactly this through the MessagingCenter, but can't pass multiple arguments. See code below:

    MessagingCenter.Subscribe<MainPage, string, string> (this, "DisplayAlert", (sender, title, message) => {
        DisplayAlert(title, message, "Ok");
    });
    

    From:
    http://forums.xamarin.com/discussion/30457/how-do-you-pass-multiple-arguments-in-the-messagingcenter#latest

  • allen.8290allen.8290 USMember

    Great ,it really solve my problem

  • fernandopfernandop USMember ✭✭

    Hi,
    how do you show a DisplayActionSheet in the View and send the answer to the ViewModel?
    I accomplished that by using MessagingCenter from both sides (from ViewModel to the View so the View shows the DisplayActionSheet, and from View to ViewModel so ViewModel gets the answer), but I am not sure if that i the correct way to do this in MVVM pattern, can somebody clarify this?

    Thanks.

  • alexrainmanalexrainman USMember ✭✭

    This is classic pattern of MVVM and it's called Dialog Service and allow you to call dialogs from your ViewModel. I think Xamarin needs to add it to Xamarin.Forms. The only one available now is https://github.com/aritchie/acr-xamarin-forms/blob/master/Samples/Samples/ViewModels/UserDialogViewModel.cs

  • FulvioFulvio AUMember ✭✭
    edited April 2015

    To add to the answer above by @JonRuskin

    This is how you implement the MessagingCenter.Subscribe<.., ..>();

    MessagingCenter.Subscribe<Application, DisplayAlertMessage> (this, "ShowAlert", async (sender, message) => {
    
        const string title = "Message";
        const string cancel = "Cancel";
    
        var result = true;
        if (!string.IsNullOrEmpty (message.Accept))
            result = await this.DisplayAlert (title, message.Message, message.Accept, cancel);
        else {
            await this.DisplayAlert (title, message.Message, cancel);
        }
    
        if (message.OnCompleted != null)
            message.OnCompleted (result);
    
    }, Application.Current);
    

    In your ContentPage/ViewModel:

    var message = new DisplayAlertMessage ();
    
    message.Message = "Are you sure?";
    message.Accept = "I'm sure!";
    message.OnCompleted += (accept) => {
        if (accept) {
            success = false;
        } else {
            success = true;
        }
    };
    

    MessagingCenter.Send<Application, DisplayAlertMessage> (Application.Current, "ShowAlert", message);

  • shanuabcshanuabc INMember

    Can we give different colors to buttons shown on alert box through DisplayAlert() method, in xamarin?

  • PhilOxenbergPhilOxenberg USMember ✭✭

    I have the same question as @shanuabc

  • ThomasMielkeThomasMielke DEMember ✭✭
    edited March 2016

    The preferrable way to do this is by implementing an interface for the page, I think.

    Add an interface:

    namespace MyApp.Interfaces
    {
        public interface IMyViewModel
        {
            void DisplayMessage(string title, string msg);
        }
    }
    

    Store the interface to the view in the view model and use the DisplayMessage member there:

    namespace MyApp.ViewModels
    {
        class MyViewModel
        {
            private IMyViewModelview;
    
            public MyViewModel(IMyViewModel view)
            {
                this.view = view;
            }
    
            ...
    
            view.DisplayMessage("Title", "Hi there!");
        }
    }
    

    Implement the interface in the page class:

    namespace MyApp.Views
    {
    public partial class MyPage : IMyViewModel 
        {
            ...
    
            public void DisplayMessage(string title, string msg)
            {
                {
    #if __ANDROID__
                    DisplayAlert(title, msg, "OK");
    #else
                    DisplayAlert(title, msg, "OK", null);
    #endif
                }
            }
        }
    }
    

    When opening the page, provide the page's interface to the view model:

    ...
    var page = new MyPage ();
    var viewmodel = new MyViewModel(page /* as IMyViewModel */ );
    page.BindingContext = viewmodel;
    Navigation.PushModalAsync(page);
    ...
    
  • pranartdechpokketpranartdechpokket THMember ✭✭

    From View , We can trace up (using .Parent Property) until we find the page. Then we can use DisplayAlert.

    Element element = this;  // this is view
    Page ifPage = null;
    do
    {
        element = element.Parent;
        ifPage = element as Page;
        if(ifPage != null)
        {
            ifPage.DisplayAlert("Hello","DisplayAlert From Any View.","OK");
            break;
        }
    }while(element != null);
    
  • voidstreamvoidstream FRMember ✭✭✭

    @xinmeng said:
    I use this method to invoke a alert display:

    var answer = await App.Current.MainPage.DisplayAlert ("You have connect to .....!", "Would you like to Clock In at once?", "Yes", "No");

    Thanks you! That was so logic but nice one guy x) You solve problem on the conception method with management exception ;)

  • GentiGaceGentiGace USMember

    @xinmeng said:
    I use this method to invoke a alert display:

    var answer = await App.Current.MainPage.DisplayAlert ("You have connect to .....!", "Would you like to Clock In at once?", "Yes", "No");

    Thank you this was for me very helpful.

  • batmacibatmaci DEMember ✭✭✭✭✭
    edited January 21

    You can also check FreshMvvm source code, it implements it perfectly for displayalert and DisplayActionSheet for ViewModels

Sign In or Register to comment.