Я пытаюсь реализовать Ooui, чтобы мои модели просмотра поддерживали ASP.NET Core и ориентировались на Интернет. У меня есть библиотека классов, которая используется в WPF, Xamarin.Forms с использованием платформы MvvmLight. Поэтому я стараюсь найти лучший подход для ooui. Совет будет оценен. На данный момент я не могу заставить DisplayAlert работать на всех страницах.

public class BaseController : Controller, IDialogService, INavigationService
{
    private static Stack<Page> _stack = null;

    protected Page CurrentPage => page.Navigation.NavigationStack.LastOrDefault();
    protected Page RootPage => page.Navigation.NavigationStack.FirstOrDefault();

    static BaseController()
    {
        _stack = new Stack<Page>();
    }

    private IHttpContextAccessor _service;
    private IApplicationBuilder app;
    protected NavigationPage page;


    private HttpContext Context
    {
        get { return _service.HttpContext; }
    }

    public string CurrentPageKey => throw new NotImplementedException();

    public BaseController()
    {
        if (!SimpleIoc.Default.IsRegistered<IDialogService>())
            SimpleIoc.Default.Register<IDialogService>(() => this);

        if (!SimpleIoc.Default.IsRegistered<INavigationService>())
            SimpleIoc.Default.Register<INavigationService>(() => this);

        _service = SimpleIoc.Default.GetInstance<IHttpContextAccessor>();
        app = SimpleIoc.Default.GetInstance<IApplicationBuilder>();
    }

    public async Task ShowError(string message, string title, string buttonText, Action afterHideCallback)
    {
        await CurrentPage.DisplayAlert(title, message, buttonText);
        afterHideCallback();
    }

    public async Task ShowError(Exception error, string title, string buttonText, Action afterHideCallback)
    {
        await CurrentPage.DisplayAlert(title, error.Message, buttonText);
        afterHideCallback();
    }

    public async Task ShowMessage(string message, string title)
    {
        await CurrentPage.DisplayAlert(title, message, "OK");
    }

    public async Task ShowMessage(string message, string title, string buttonText, Action afterHideCallback)
    {
        await CurrentPage.DisplayAlert(title, message, buttonText);
        afterHideCallback();
    }

    public async Task<bool> ShowMessage(string message, string title, string buttonConfirmText, string buttonCancelText, Action<bool> afterHideCallback)
    {
        var result = await page.DisplayAlert(title, message, buttonConfirmText, buttonCancelText);
        afterHideCallback(result);
        return result;
    }

    public async Task ShowMessageBox(string message, string title)
    {
        await CurrentPage.DisplayAlert(title, message, "OK");
    }

    public void GoBack()
    {
        page.PopAsync();
        page.PushAsync(_stack.Pop());
    }

    public void NavigateTo(string pageKey)
    {
        _stack.Push(CurrentPage);

        page.PopAsync();            
        page.PushAsync(SimpleIoc.Default.GetInstance<Page>(pageKey));
    }

    public void NavigateTo(string pageKey, object parameter)
    {
        throw new NotImplementedException();
    }
}



public class HomeController : BaseController
    {        
        public HomeController()
            : base()
        {
            SimpleIoc.Default.Register<Page>(() => new Next(), "Next");
            SimpleIoc.Default.Register<Page>(() => new MainPage(), "MainPage");
        }

        public IActionResult Index()
        {
            page = new NavigationPage(new MainPage());            
            //NavigateTo("MainPage");
            return new ElementResult(page.GetOouiElement(), "Hello from XAML!");
        }

        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
3
Cédric B 19 Сен 2018 в 20:55

2 ответа

Лучший ответ

Я наконец то придумал !!!

public abstract class OouiMvcProgram<T> : Controller where T : class {
    private string MainRoute => "{controller=" + typeof(T).Name + "}/{action=StartUp}/{id?}";
    private string ErrorRoute => $"/{typeof(T).Name}/Error";

    private static XamarinOouiApplication _xamarinApplication = null;

    /// <summary>
    /// The main path to display
    /// </summary>
    protected abstract string MainPageName { get; }

    /// <summary>
    /// Title of the window
    /// </summary>
    protected abstract string Title { get; }

    private static XamarinOouiService Navigation => _xamarinApplication.Service;

    /// <summary>
    /// Let's start the xamarin application
    /// </summary>
    /// <param name="xamarinApplication">Xamarin application</param>
    /// <param name="args"></param>
    public static void StartApplication(XamarinOouiApplication xamarinApplication, string[] args)
    {
        _xamarinApplication = xamarinApplication;

        MessagingCenter.Subscribe<Page, AlertArguments>
            (_xamarinApplication, Page.AlertSignalName, PatchDisplayAlert);

        WebHost.CreateDefaultBuilder(args)
           .UseStartup<T>()
           .Build()
           .Run();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender">Calling page</param>
    /// <param name="arguments"></param>
    private static void PatchDisplayAlert(Page sender, AlertArguments arguments)
    {
        //DisplayAlert on z-index
        var element = Navigation.CurrentPage.GetOouiElement();
        if (element.GetAttribute("style") == null)
            element.SetAttribute("style", "{z-index:9999;}");
    }

    /// <summary>
    /// This method gets called by the runtime. 
    /// Use this method to add services to the container.
    /// For more information on how to configure your application, 
    /// visit https://go.microsoft.com/fwlink/?LinkID=398940
    /// </summary>
    /// <param name="services"></param>
    public virtual void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }

    /// <summary>
    /// This method gets called by the runtime. 
    /// Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler(ErrorRoute);
        }

        app.UseOoui();
        app.UseMvc(routes => routes.MapRoute("default", MainRoute));
    }

    public IActionResult StartUp()
    {
        Navigation.Start(MainPageName);

        var element = Navigation.MainPage.GetOouiElement();

        Navigation.CurrentViewModel?.OnOouiServiceEnabled();

        return new ElementResult(element, Title);
    }        

    public IActionResult Error()
    {
        var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        return new ElementResult(GetErrorPage(exceptionFeature).GetOouiElement(), Title);
    }

    /// <summary>
    /// Get the details of the exception that occurred
    /// https://scottsauber.com/2017/04/03/adding-global-error-handling-and-logging-in-asp-net-core/
    /// </summary>
    /// <param name="exceptionFeature"></param>
    /// <returns></returns>
    protected virtual ContentPage GetErrorPage(IExceptionHandlerPathFeature exceptionFeature)
    {
        var errorPage = new ContentPage();
        if (exceptionFeature != null)
        {
            // Get which route the exception occurred at
            string routeWhereExceptionOccurred = exceptionFeature.Path;

            // Get the exception that occurred
            Exception exceptionThatOccurred = exceptionFeature.Error;

            // TODO: Do something with the exception
            // Log it with Serilog?
            // Send an e-mail, text, fax, or carrier pidgeon?  Maybe all of the above?
            // Whatever you do, be careful to catch any exceptions, otherwise you'll end up with a blank page and throwing a 500
            errorPage.Content = new Xamarin.Forms.Label()
            {
                Text = routeWhereExceptionOccurred + "\n" +
                       exceptionThatOccurred.Message
            };
        }
        return errorPage;
    }                

    public UITarget FindByName(string name)
    {
        var target = Navigation.CurrentPage.GetEventTarget(name);
        return new UITarget(
            add:
            (eventType, handler) => target.AddEventListener(eventType, 
            (element, args) => handler.Invoke(element, args)),

            remove:
            (eventType, handler) => target.RemoveEventListener(eventType, 
            (element, args) => handler.Invoke(element, args)));
    }
}
0
Cédric B 28 Окт 2018 в 19:17

Основываясь на вашем комментарии, мое предположение было правильным.

Диалоговое окно отображается, но не отображается спереди. Определение свойства CSS z-index для элемента, по-видимому, решает проблему.

Если это задано как HTML ...

<div class="most-top"> ... </div>

.. ваш css может выглядеть так ..

.most-top {
    z-index: 99;
}
0
Tobias Würth 3 Окт 2018 в 07:35