Piszę aplikację, która powinna mieć możliwość uruchamiania wielu widoków w celu edytowania różnych dokumentów w ich własnym oknie. Napisałem trochę kodu, który działa, ale mam z tym problemy. Kod, który napisałem, jest oparty na próbce Wielokrotne wyświetlenia dostarczonej przez Microsoft (https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/MultipleViews).Problemy z UWP z wieloma widokami
Mam głównie dwa problemy. Pierwszy z nich polega na tym, że jeśli zamknę główny widok, czyli pierwsze okno, które było otwarte po uruchomieniu aplikacji, nie mogę otworzyć żadnych nowych widoków/okien, klikając w kafelku aplikacji lub otwierając powiązany typ pliku, dopóki nie zamknę wszystkie widoki/okna i ponownie uruchom aplikację. Drugim jest to, że gdy próbuję otworzyć nowy widok/okno z MainPage.xaml.cs, aplikacja po prostu zawiesza się.
Kod, który używam do zarządzania widoki w App.xaml.cs jest następujący:
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();
}
}
}
kodu używam spróbować uruchomić nowy widok/okno z MainPage.xaml.cs:
((App)App.Current).LoadNewView();
Czytałem dokumentację firmy Microsoft, aby spróbować zrozumieć, co jest problemem, ale ja nadal nie rozumiem, jak dokładnie zrobić Wiele widoków działa, jak gdyby klasa App instancji za każdym razem otwierać nowy widok/okno.
Naprawdę doceniam pomoc.
Ten kod 'currentPage.LoadNewFile();' wywołuje plik LoadNewFp. Czy napisałeś inną metodę "LoadNewFile()" w swojej Mainpage.xaml.cs? Dlaczego umieszczasz cały kod w App.xaml.cs? Lepiej załadować cały twój kod. –
Tak, napisałem metodę LoadNewFile() na mojej stronie MainPage.xaml.cs i wstawiłem cały kod dla wielu widoków w App.xaml.cs, więc nie muszę przepisywać kodu, ale próbowałem utworzyć nowy widok/okno z mojej MainPage.xaml.cs z tymi samymi błędami. Aplikacja ulega awarii podczas CoreApplication.CreateNewView(). Dispatcher.RunAsync (CoreDispatcherPriority.Normalny,() => działa w metodzie createMainPageAsync(), a najdziwniejsze jest to, że próbuje otworzyć inny debugger zamiast Visual Studio –
W takim przypadku prześlij cały swój kod, w przeciwnym razie ludzie nie będą mogli pomóc bez kodu błędu, szczegóły błędu. –