i have a toolbar in my content page where there is one item called add , on clicking over add i want to open DisplayActionSheet
i have created ContentPage
Toolbar
in xaml
and attached ICommand
to it in view model. Now DisplayActionSheet
is accessible only in View hence i am not sure how will i able to access it and render it from view model.
xaml file
<ContentPage.ToolbarItems>
<ToolbarItem Name="" Icon="ic_add.png" Order="Primary" Priority="0" Command="{Binding OnAddContactCommand}"/>
<ToolbarItem Name="" Icon="ic_search.png" Order="Primary" Priority="1" Command="{Binding OnContactSearchCommand}" />
</ContentPage.ToolbarItems>
View model
public ICommand OnContactSearchCommand => new Command(OnContactSearch);
public ICommand OnAddContactCommand => new Command(OnAddContactSearch);
events
private async void OnAddContactSearch()
{
//var action = await DisplayActionSheet(AppResources.select_contact_source, AppResources.cancel, null, AppResources.manual, AppResources.phonebook);
}
private void OnContactSearch()
{
Debug.WriteLine("OnContactSearch");
}
Like @Alessandro said Application.Current.MainPage
works fine for action sheets and alerts as well. To hide view specific stuff from view model I created an IMessageBoxService
which is injected into the view models' contructors that need it. Note that I am using the Autofac IoC container. For Xamarin's DependencyService you have change the constructors and look up the service in code.
IMessageBoxService.cs
public interface IMessageBoxService
{
void ShowAlert(string title, string message, Action onClosed = null);
// ...
Task<string> ShowActionSheet(string title, string cancel, string destruction, string[] buttons = null);
}
MessageBoxService.cs
public class MessageBoxService : IMessageBoxService
{
private static Page CurrentMainPage { get { return Application.Current.MainPage; } }
public async void ShowAlert(string title, string message, Action onClosed = null)
{
await CurrentMainPage.DisplayAlert(title, message, TextResources.ButtonOK);
onClosed?.Invoke();
}
public async Task<string> ShowActionSheet(string title, string cancel, string destruction = null, string[] buttons = null)
{
var displayButtons = buttons ?? new string[] { };
var action = await CurrentMainPage.DisplayActionSheet(title, cancel, destruction, displayButtons);
return action;
}
}
AppSetup.cs
protected void RegisterDependencies(ContainerBuilder cb)
{
// ...
cb.RegisterType<MessageBoxService>().As<IMessageBoxService>().SingleInstance();
}
Usage
public class EditProductViewModel : AddProductViewModel
{
private IMessageBoxService _messageBoxService;
public ICommand DeleteCommand { get; set; }
public EditProductViewModel(IPageNavigator navigator, IMessenger messenger,
IMessageBoxService messageBoxService, TagDataStore tagDataStore) : base(navigator, messenger, tagDataStore)
{
_messageBoxService = messageBoxService;
DeleteCommand = new Command(DeleteItem);
}
...
private async void DeleteItem()
{
var action = await _messageBoxService.ShowActionSheet(TextResources.MenuTitleDeleteProduct,
TextResources.ButtonCancel, TextResources.ButtonDelete);
if (action == TextResources.ButtonDelete)
{ } // delete
If you are doing viewmodel first navigation (s. Xamarin or Jonathan Yates' blog) you may chose to make this part of the Navigator service. It's a matter of taste
try with
Application.Current.MainPage.DisplayActionSheet();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With