Xamarin Forms iOS Open File Dependency within a MessagingCenter Subscription.

RyanSposatoRyanSposato USMember
edited June 2016 in Xamarin.Forms

I am having an issue getting the UINavigationController in the iOS implementation of the Open File Dependency. I loop through the whole iOS stack and the UINavigationController is always null. This looks to only occur when I call it from within a Message Subscription.

Here is my code:
iOS Open FIle Dependency:

public class OpenFileImplementation : IOpenFile
        {
            public OpenFileImplementation()
            {

            }

            public void OpenFile(string filePath)
            {
                FileInfo fi = new FileInfo(filePath);

                QLPreviewController previewController = new QLPreviewController();
                previewController.DataSource = new PDFPreviewControllerDataSource(fi.FullName, fi.Name);

                UINavigationController controller = FindNavigationController();
                if (controller != null)
                    controller.PresentViewController(previewController, true, null);
                else
                    UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(
                        previewController, true, null);

            }

            private UINavigationController FindNavigationController()
            {
                //Check to see if the roomviewcontroller is the navigationcontroller.
                foreach (var window in UIApplication.SharedApplication.Windows)
                {
                    if (window.RootViewController.NavigationController != null)
                        return window.RootViewController.NavigationController;
                    else
                    {
                        UINavigationController val = CheckSubs(window.RootViewController.ChildViewControllers);
                        if (val != null)
                            return val;
                    }
                }
                //  var viewcontroller = UIApplication.SharedApplication.KeyWindow.RootViewController as UIViewController;
                // viewcontroller.NavigationController = new UINavigationController();
                // return new UINavigationController(viewcontroller);
                return null;
            }

            private UINavigationController CheckSubs(UIViewController[] controllers)
            {
                foreach (var controller in controllers)
                {
                    if (controller.NavigationController != null)
                        return controller.NavigationController;
                    else
                    {
                        UINavigationController val = CheckSubs(controller.ChildViewControllers);
                        if (val != null)
                            return val;
                    }
                }
                return null;
            }

            public class PDFItem : QLPreviewItem
            {
                string title;
                string uri;

                public PDFItem(string title, string uri)
                {
                    this.title = title;
                    this.uri = uri;
                }

                public override string ItemTitle
                {
                    get { return title; }
                }

                public override NSUrl ItemUrl
                {
                    get { return NSUrl.FromFilename(uri); }
                }
            }
        }

        public class PDFPreviewControllerDataSource : QLPreviewControllerDataSource
        {
            string url = "";
            string filename = "";

            public PDFPreviewControllerDataSource(string url, string filename)
            {
                this.url = url;
                this.filename = filename;
            }

            public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
            {
                return new OpenFileImplementation.PDFItem(filename, url);
            }

            public override nint PreviewItemCount(QLPreviewController controller)
            {
                return 1;
            }
        }

My call to it:

 public partial class MeetingDetailsPage
            {
                private readonly MeetingDetailViewModel viewmodel;
                public MeetingDetailsPage(VwMeetings meeting)
                {
                    viewmodel = new MeetingDetailViewModel(meeting);
                    this.InitializeComponent();
                    BindingContext = viewmodel.Meeting;
                    // ExtendedButtonBack.BindingContext = viewmodel;
                    listView.BindingContext = viewmodel;

                }

                private void DocumentsList_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
                {
                    UserDialogs.Instance.ShowLoading("File Downloading", MaskType.Gradient);
                    DownloadMessage message = new DownloadMessage()
                    {
                        FileName = ((VwMeetingsDocuments)((ListView)sender).SelectedItem).MEET_NUMB + "_" + ((VwMeetingsDocuments)((ListView)sender).SelectedItem).FILE_NAME,
                        Type = "Meeting"
                    };
                    MessagingCenter.Send(message, "Download");
                    //  DependencyService.Get<IOpenFile>().OpenFile("/private/var/mobile/Containers/Data/Application/3333333333/tmp/FILENAME.docx");
                }

                protected override void OnAppearing()
                {
                    MessagingCenter.Subscribe<DownloadFinishedMessage>(this, "DownloadFinishedMessage", message =>
                    {
                        Device.BeginInvokeOnMainThread(() =>
                        {
                            UserDialogs.Instance.HideLoading();
                            DependencyService.Get<IOpenFile>().OpenFile(message.FilePath);
                        });
                    });
                    base.OnAppearing();
                }

                protected override void OnDisappearing()
                {
                    base.OnDisappearing();
                    MessagingCenter.Unsubscribe<DownloadFinishedMessage>(this, "DownloadFinishedMessage");
                }

                private void MeetingDetailsPage_OnDisappearing(object sender, EventArgs e)
                {

                    this.BindingContext = null;
                }
            }

I'm subscribing to the Download Message in the AppDelegate.cs file, and it's downloading the file correctly. You can see I commented out hard coding the filename into the page. When I don't use messaging services it works perfectly. Any idea on how I can get the UINavigationController?

Posts

  • RyanSposatoRyanSposato USMember

    I was able to get it to come up.

    I used this code:

    public void OpenFile(string filePath)
            {
                FileInfo fi = new FileInfo(filePath);
    
                QLPreviewController previewController = new QLPreviewController();
                previewController.DataSource = new PDFPreviewControllerDataSource(fi.FullName, fi.Name);
    
                UINavigationController controller = FindNavigationController();
                if (controller != null)
                    controller.PresentViewController(previewController, true, null);
                else
                { 
                    UINavigationController nav = new UINavigationController(previewController);
                    UIApplication.SharedApplication.Windows[1].RootViewController.PresentViewController(
                        nav, true, null);
                }
            }
    

    However, the window does not have a done button now to go back. I am unsure how to get this to appear on the keywindow as well I do it does not appear.

  • RyanSposatoRyanSposato USMember

    I was able to fix that by adding it as a childviewcontroller.

  • RyanSposatoRyanSposato USMember

    I'm actually still having issues with this. Right after the app is installed I can never get the Preview window to contain a "done" button or a way back to the previous page. The presentedviewcontroller is always null.

Sign In or Register to comment.