2016-04-17 20 views
7

Sto scrivendo un'app che dovrebbe essere in grado di eseguire più viste per modificare diversi documenti ciascuno nella propria finestra. Ho scritto del codice che funziona, ma ho qualche problema con esso. Il codice che ho scritto si basa sull'esempio Multiple Views fornito da Microsoft (https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/MultipleViews).Problemi UWP con più viste

Ho principalmente due problemi. Il primo è se chiudo la vista principale, ovvero la prima finestra aperta all'avvio dell'applicazione, quindi non posso aprire nessuna nuova vista/finestra facendo clic sul riquadro dell'app o aprendo un tipo di file associato, finché non chiudo tutte le viste/finestre e riavvia l'app. Il secondo è che quando provo ad aprire una nuova vista/finestra da MainPage.xaml.cs, l'app si blocca.

Il codice che uso per gestire i punti di vista in App.xaml.cs è il seguente:

sealed partial class App : Application 
{ 
    //I use this boolean to determine if the application has already been launched once 
    private bool alreadyLaunched = false; 

    public ObservableCollection<ViewLifetimeControl> SecondaryViews = new ObservableCollection<ViewLifetimeControl>(); 
    private CoreDispatcher mainDispatcher; 
    public CoreDispatcher MainDispatcher 
    { 
     get 
     { 
      return mainDispatcher; 
     } 
    } 

    private int mainViewId; 
    public int MainViewId 
    { 
     get 
     { 
      return mainViewId; 
     } 
    } 

    public App() 
    { 
     this.InitializeComponent(); 
     this.Suspending += OnSuspending; 
    } 

    protected override async void OnLaunched(LaunchActivatedEventArgs e) 
    { 
     Frame rootFrame = Window.Current.Content as Frame; 

     if (rootFrame == null) 
     { 
      rootFrame = new Frame(); 

      rootFrame.NavigationFailed += OnNavigationFailed; 

      if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 
      { 
       //TODO: Load state from previously suspended application 
      } 

      // Place the frame in the current Window 
      Window.Current.Content = rootFrame; 
     } 

     if (rootFrame.Content == null) 
     { 
      alreadyLaunched = true; 
      rootFrame.Navigate(typeof(MainPage), e.Arguments); 
     } 
     else if(alreadyLaunched) 
     { 
      var selectedView = await createMainPageAsync(); 
      if (null != selectedView) 
      { 
       selectedView.StartViewInUse(); 
       var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
        selectedView.Id, 
        ViewSizePreference.Default, 
        ApplicationView.GetForCurrentView().Id, 
        ViewSizePreference.Default 
        ); 

       await selectedView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
       { 
        var currentPage = (MainPage)((Frame)Window.Current.Content).Content; 
        Window.Current.Activate(); 
       }); 

       selectedView.StopViewInUse(); 
      } 
     } 
     // Ensure the current window is active 
     Window.Current.Activate(); 
    } 

    protected override async void OnFileActivated(FileActivatedEventArgs args) 
    { 
     base.OnFileActivated(args); 

     if (alreadyLaunched) 
     { 
      //Frame rootFrame = Window.Current.Content as Frame; 
      //((MainPage)rootFrame.Content).OpenFileActivated(args); 
      var selectedView = await createMainPageAsync(); 
      if (null != selectedView) 
      { 
       selectedView.StartViewInUse(); 
       var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
        selectedView.Id, 
        ViewSizePreference.Default, 
        ApplicationView.GetForCurrentView().Id, 
        ViewSizePreference.Default 
        ); 

       await selectedView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
       { 
        var currentPage = (MainPage)((Frame)Window.Current.Content).Content; 
        Window.Current.Activate(); 
        currentPage.OpenFileActivated(args); 
       }); 

       selectedView.StopViewInUse(); 
      } 
     } 
     else 
     { 
      Frame rootFrame = new Frame(); 
      rootFrame.Navigate(typeof(MainPage), args); 
      Window.Current.Content = rootFrame; 
      Window.Current.Activate(); 
      alreadyLaunched = true; 
     } 
    } 

    partial void Construct(); 
    partial void OverrideOnLaunched(LaunchActivatedEventArgs args, ref bool handled); 
    partial void InitializeRootFrame(Frame frame); 

    partial void OverrideOnLaunched(LaunchActivatedEventArgs args, ref bool handled) 
    { 
     // Check if a secondary view is supposed to be shown 
     ViewLifetimeControl ViewLifetimeControl; 
     handled = TryFindViewLifetimeControlForViewId(args.CurrentlyShownApplicationViewId, out ViewLifetimeControl); 
     if (handled) 
     { 
      var task = ViewLifetimeControl.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
      { 
       Window.Current.Activate(); 
      }); 
     } 
    } 

    partial void InitializeRootFrame(Frame frame) 
    { 
     mainDispatcher = Window.Current.Dispatcher; 
     mainViewId = ApplicationView.GetForCurrentView().Id; 
    } 

    bool TryFindViewLifetimeControlForViewId(int viewId, out ViewLifetimeControl foundData) 
    { 
     foreach (var ViewLifetimeControl in SecondaryViews) 
     { 
      if (ViewLifetimeControl.Id == viewId) 
      { 
       foundData = ViewLifetimeControl; 
       return true; 
      } 
     } 
     foundData = null; 
     return false; 
    } 

    private async Task<ViewLifetimeControl> createMainPageAsync() 
    { 
     ViewLifetimeControl viewControl = null; 
     await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
     { 
      // This object is used to keep track of the views and important 
      // details about the contents of those views across threads 
      // In your app, you would probably want to track information 
      // like the open document or page inside that window 
      viewControl = ViewLifetimeControl.CreateForCurrentView(); 
      viewControl.Title = DateTime.Now.ToString(); 
      // Increment the ref count because we just created the view and we have a reference to it     
      viewControl.StartViewInUse(); 

      var frame = new Frame(); 
      frame.Navigate(typeof(MainPage), viewControl); 
      Window.Current.Content = frame; 
      // This is a change from 8.1: In order for the view to be displayed later it needs to be activated. 
      Window.Current.Activate(); 
      //ApplicationView.GetForCurrentView().Title = viewControl.Title; 
     }); 

     ((App)App.Current).SecondaryViews.Add(viewControl); 

     return viewControl; 
    } 

    void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 
    { 
     throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 
    } 

    private void OnSuspending(object sender, SuspendingEventArgs e) 
    { 
     var deferral = e.SuspendingOperation.GetDeferral(); 
     //TODO: Save application state and stop any background activity 
     deferral.Complete(); 
    } 

    //I call this function from MainPage.xaml.cs to try to open a new window 
    public async void LoadNewView() 
    { 
     var selectedView = await createMainPageAsync(); 
     if (null != selectedView) 
     { 
      selectedView.StartViewInUse(); 
      var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
       selectedView.Id, 
       ViewSizePreference.Default, 
       ApplicationView.GetForCurrentView().Id, 
       ViewSizePreference.Default 
       ); 

      await selectedView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
      { 
       var currentPage = (MainPage)((Frame)Window.Current.Content).Content; 
       Window.Current.Activate(); 
       currentPage.LoadNewFile(); 
      }); 

      selectedView.StopViewInUse(); 
     } 
    } 
} 

Il codice che uso per cercare di lanciare una nuova vista/finestra da MainPage.xaml.cs:

((App)App.Current).LoadNewView(); 

ho letto la documentazione di Microsoft per cercare di capire qual è il problema, ma io continuo a non capire come esattamente fare più Visualizzazioni lavoro, come se la classe App un'istanza ogni volta che apro un nuovo vista/finestra.

Apprezzerei molto l'aiuto.

+0

Questo codice 'currentPage.LoadNewFile();' sta richiamando il LoadNewFile della pagina principale. Hai scritto un altro metodo 'LoadNewFile()' in Mainpage.xaml.cs? Perché inserisci tutto il codice in App.xaml.cs? Meglio caricare tutto il tuo codice. –

+0

Sì, ho scritto il metodo LoadNewFile() nel mio MainPage.xaml.cs e ho inserito tutto il codice per più viste in App.xaml.cs in modo da non dover riscrivere il codice, ma ho provato a creare la nuova vista/finestra dal mio MainPage.xaml.cs con gli stessi errori. L'app si arresta in modo anomalo quando CoreApplication.CreateNewView(). Dispatcher.RunAsync (CoreDispatcherPriority.Normal,() => viene eseguito nel metodo createMainPageAsync() e la cosa più strana è che tenta di aprire un altro debugger anziché Visual Studio –

+0

In tal caso, carica tutto il codice, altrimenti le persone non possono aiutarti senza il codice di errore, dettagli circa l'errore. –

risposta

2

Ho trovato la soluzione ai miei problemi e in realtà ho deciso di non utilizzare il controllo ViewLifeTime fornito con l'esempio.

Il problema è che quando la vista principale è chiusa è necessario utilizzare il metodo Dispatcher.RunAsync() da una delle altre viste che sono ancora aperte per eseguirlo quel filo

Ecco il codice che ho' ve cambiato nella mia App.xaml.cs per chiunque sia interessato:

public bool isMainViewClosed = false; 
public ObservableCollection<CoreApplicationView> secondaryViews = new ObservableCollection<CoreApplicationView>(); 

//... 

protected override async void OnLaunched(LaunchActivatedEventArgs e) 
    { 
     Frame rootFrame = Window.Current.Content as Frame; 

     if (rootFrame == null) 
     { 
      rootFrame = new Frame(); 

      rootFrame.NavigationFailed += OnNavigationFailed; 

      if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 
      { 
       //TODO: Load state from previously suspended application 
      } 
      Window.Current.Content = rootFrame; 
     } 

     if (rootFrame.Content == null) 
     { 
      alreadyLaunched = true; 
      rootFrame.Navigate(typeof(MainPage), e.Arguments); 
     } 
     else if(alreadyLaunched) 
     { 
    //If the main view is closed, use the thread of one of the views that are still open 
      if(isMainViewClosed) 
      { 
       int newViewId = 0; 
       await secondaryViews[0].Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
       { 
        var currentPage = (MainPage)((Frame)Window.Current.Content).Content; 
        Window.Current.Activate(); 
        currentPage.NewWindow(); 
        newViewId = ApplicationView.GetForCurrentView().Id; 
       }); 
       bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId); 
      } 
      else 
      { 
       CoreApplicationView newView = CoreApplication.CreateNewView(); 
       int newViewId = 0; 
       await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
       { 
        Frame frame = new Frame(); 
        frame.Navigate(typeof(MainPage), null); 
        Window.Current.Content = frame; 
        var currentPage = (MainPage)((Frame)Window.Current.Content).Content; 
        Window.Current.Activate(); 

        secondaryViews.Add(CoreApplication.GetCurrentView()); 
        newViewId = ApplicationView.GetForCurrentView().Id; 
       }); 
       bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId); 
      } 
     } 
     Window.Current.Activate(); 
    } 
-1

non View (la tua) vita lontano ... evviva,

int idCreate = 0; List<int> idSaved = new List<int>(); 
protected override async void OnLaunched(LaunchActivatedEventArgs e) 
{ 
    Frame rootFrame = Window.Current.Content as Frame; 
    if (rootFrame == null) 
    { 
     rootFrame = new Frame(); 
     rootFrame.NavigationFailed += OnNavigationFailed; 
     Window.Current.Content = rootFrame; 
    } 

    if (rootFrame.Content == null) 
    { 
     rootFrame.Navigate(typeof(MainPage), e.Arguments); 
     idSaved.Add(ApplicationView.GetForCurrentView().Id); 
    } 
    else 
    { 
     var create = CoreApplication.CreateNewView(); 
     await create.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
     { 
      var frame = new Frame(); 
      frame.Navigate(typeof(MainPage), e.Arguments); 
      Window.Current.Content = frame; 
      Window.Current.Activate(); 

      idCreate = ApplicationView.GetForCurrentView().Id; 
     }); 

     for(int i = idSaved.Count - 1; i >= 0; i--) 
      if (await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
        idCreate, ViewSizePreference.UseMinimum, 
        idSaved[i], ViewSizePreference.UseMinimum) 
       ) break; 

     idSaved.Add(idCreate); 
    } 
    Window.Current.Activate(); 
} 
+3

Se si desidera cancellare la risposta, fare semplicemente clic sul pulsante Elimina. – FrankerZ

+0

@FrankerZ, gli utenti non registrati non possono cancellare le loro risposte. –

7

in realtà il modo corretto di essere ancorain grado di aprire nuove finestre dopo la chiusura principale è quello di utilizzare uno dei sovraccarichi forniti da TryShowAsStandaloneAsync.

protected override async void OnLaunched(LaunchActivatedEventArgs e) 
{ 
    // Create the newWindowId and stuff... 

    await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newWindowId, 
     ViewSizePreference.Default, 
     e.CurrentlyShownApplicationViewId, 
     ViewSizePreference.Default); 

In sostanza, è necessario specificare il terzo parametroanchorViewId che è

l'ID della finestra di chiamata (ancora).

In questo caso, è sufficiente passare e.CurrentlyShownApplicationViewId.

Problemi correlati