I have a Windows Phone 8.1 app. It consists of 2 pages. On the first page (MainPage.xaml) there is ListView and few buttons. One buton allow to multiselect items on the list. In code I handle back buton, so when user click back in multiselection mode the app won't terminate, but just exit the multiselection mode.
private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
if (MultiSelectionButton.Visibility == Visibility.Collapsed)
{
DeleteSelectionButton.Visibility = Visibility.Collapsed;
MultiSelectionButton.Visibility = Visibility.Visible;
TripListView.SelectionMode = ListViewSelectionMode.None;
TripListView.IsItemClickEnabled = true;
e.Handled = true;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
this.navigationHelper.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
this.navigationHelper.OnNavigatedFrom(e);
}
On the second page (HubPage.xaml) there is Hub control, HubSection, and in the HubSection ListView. Similar to the first page I dont want to go back to previous page from selection mode.
private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
if (_PeopleListViewInstance.SelectionMode == ListViewSelectionMode.Multiple)
{
_PeopleListViewInstance.SelectionMode = ListViewSelectionMode.None;
DeleteSelectionButton.Visibility = Visibility.Collapsed;
MultiSelectionButton.Visibility = Visibility.Visible;
_PeopleListViewInstance.IsItemClickEnabled = true;
e.Handled = true;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_vm.Trip = (Trip) e.Parameter;
DataContext = _vm;
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
this.navigationHelper.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
this.navigationHelper.OnNavigatedFrom(e);
}
Code on the first page works fine, but the second one doesn't.
What I'm doing wrong?
Related
I have a WebView in a page and I'm playing a youtube video. When I navigate away from the page to the previous page on the stack, the youtube video in the web view keeps playing the youtube video. Anyone know how to prevent this and kill the WebView when the user navigates away from the page?
EDIT:
Here is how I'm navigating back
private void HtmlViewerPage_BackRequested(object sender, BackRequestedEventArgs e)
{
if (Viewer.CanGoBack)
{
Viewer.GoBack();
e.Handled = true;
return;
}
{
GoBack will navigate the frame stack. It then allows the youtube video to continue to play in the background.
EDIT: I created a sample project that demonstrates my issue.
https://github.com/themimcompany/WebViewIssue
You've registered BackRequested event in MainPage and WebViewPage, but you have not unregistered it when you navigate to other pages. This will cause your issue. When you click back button on WebViewPage, the BackRequested handler will be triggered multi times.
You could remove it in OnNavigatingFrom handler on MainPage.xaml.cs and WebViewPage.xaml.cs.
Please see the following code:
public sealed partial class WebViewPage : Page
{
public WebViewPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var currentView = SystemNavigationManager.GetForCurrentView();
currentView.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
SystemNavigationManager.GetForCurrentView().BackRequested += WebViewPage_BackRequested;
var site = (e.Parameter as Dictionary<string, string>)["site"];
WebViewer.Navigate(new Uri(site));
}
private void WebViewPage_BackRequested(object sender, BackRequestedEventArgs e)
{
//always try to go back within the WebView first, then try the frame!
if (this.Frame.CanGoBack)
{
if (WebViewer.CanGoBack)
{
WebViewer.GoBack();
e.Handled = true;
}
else
{
WebViewer.NavigateToString("<html>Unloaded.</html>");
WebViewer.NavigateToString("");
var source = WebViewer.Source; // is cleared to null
Frame.GoBack();
e.Handled = true;
}
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
SystemNavigationManager.GetForCurrentView().BackRequested -= WebViewPage_BackRequested;
}
}
//MainPage.xaml.cs
private void AppBackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
return;
// If we can go back and the event has not already been handled, do so.
if (rootFrame.CanGoBack && e.Handled == false)
{
e.Handled = true;
rootFrame.GoBack();
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var currentView = SystemNavigationManager.GetForCurrentView();
currentView.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
SystemNavigationManager.GetForCurrentView().BackRequested += AppBackRequested;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
SystemNavigationManager.GetForCurrentView().BackRequested -= AppBackRequested;
}
How about overriding the OnNavigatingFrom method and stop the webview?
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
}
Inside the method try setting the WebView to null, or setting the Source to null or something else
This will stop it:
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
// this will stop any video from playing back.
WebView.NavigateToString("<html>Unloaded.</html>");
base.OnNavigatingFrom(e);
}
I would like to use the back function in the UWP in the App.xaml.cs file to change the visibility property of a grid (grid1) on the MainPage.xaml file.
//Go Back
public void App_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
if(MainPage.MyGlobals.pageLocation == 0)
{
//Do Nothing
}
else if(MainPage.MyGlobals.pageLocation == 1)
{
MainPage.grid1.Visibility = Visibility.Collapsed;
MainPage.MyGlobals.pageLocation = 0;
}
}
I know it's not typical practice to change xaml elements' properties from a different page, but I would really like to change how the back feature works in this app. I believe I have to make the grid pubic, but even when I (thought I) found a way to do that I still couldn't change the properties of the grid with the way I have it written in my code.
As you've mentioned, changing XAML elements' properties from a different page is not a good practice. We can just use SystemNavigationManager.BackRequested event in MainPage like following to change the visibility of a grid.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested += Page_BackRequested;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested -= Page_BackRequested;
}
private void Page_BackRequested(object sender, BackRequestedEventArgs e)
{
if (MyGrid.Visibility == Visibility.Visible)
{
MyGrid.Visibility = Visibility.Collapsed;
e.Handled = true;
}
else
{
if (this.Frame.CanGoBack)
{
this.Frame.GoBack();
e.Handled = true;
}
}
}
And if you want to take advantage of the back function in App.xaml.cs and use a different function in MainPage, you can add a event in App that wraps SystemNavigationManager.BackRequested to allow other pages to override the default behavior by subscribing to this event like following:
public event EventHandler<BackRequestedEventArgs> BackRequested;
private void App_BackRequested(object sender, BackRequestedEventArgs e)
{
BackRequested?.Invoke(sender, e);
Frame rootFrame = Window.Current.Content as Frame;
if (!e.Handled && rootFrame != null && rootFrame.CanGoBack)
{
rootFrame.GoBack();
e.Handled = true;
}
}
Then in MainPage, subscribe and unsubscribe this event like:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
(Application.Current as App).BackRequested += Page_BackRequested;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
(Application.Current as App).BackRequested -= Page_BackRequested;
}
It doesn't work because you're trying to access the Grid as if it was a static property of the MainPage. You need a reference to the MainPage instance to manipulate the Grid, but all in all it is a really bad practice. You should have a look at the UWP/WP 8.1 navigation events.
Let's assume the following Situation:
a Control (e.g. a Button) has an attached behavior to enable a Drag&Drop-Operation
<Button Content="test">
<i:Interaction.Behaviors>
<SimpleDragBehavior/>
</i:Interaction.Behaviors>
</Button>
And the SimpleDragBehavior
public class SimpleDragBehavior: Behavior<Button>
{
protected override void OnAttached ()
{
AssociatedObject.MouseLeftButtonDown += OnAssociatedObjectMouseLeftButtonDown;
AssociatedObject.MouseLeftButtonUp += OnAssociatedObjectMouseLeftButtonUp;
AssociatedObject.MouseMove += OnAssociatedObjectMouseMove;
mouseIsDown = false;
}
private bool mouseIsDown;
private void OnAssociatedObjectMouseMove (object sender, MouseEventArgs e)
{
if (mouseIsDown)
{
AssociatedObject.Background = new SolidColorBrush(Colors.Red);
DragDrop.DoDragDrop((DependencyObject)sender,
AssociatedObject.Content,
DragDropEffects.Link);
}
}
private void OnAssociatedObjectMouseLeftButtonUp (object sender, MouseButtonEventArgs e)
{
mouseIsDown = false;
}
private void OnAssociatedObjectMouseLeftButtonDown (object sender, MouseButtonEventArgs e)
{
mouseIsDown = true;
}
}
The task now is to determine when the drag ends, to restore the orignal backgound of the button.
This is no problem when droped on an drop-target. But how do i recognize a drop on something which isn't a drop-target? In the worst case: outside the window?
DragDrop.DoDragDrop returns after drag-and-drop operation is completed.
Yes, "Initiates a drag-and-drop operation" is confusing, since it could be read as "start drag-and-drop and return":
private void OnAssociatedObjectMouseMove (object sender, MouseEventArgs e)
{
if (mouseIsDown)
{
AssociatedObject.Background = new SolidColorBrush(Colors.Red);
var effects = DragDrop.DoDragDrop((DependencyObject)sender,
AssociatedObject.Content,
DragDropEffects.Link);
// this line will be executed, when drag/drop will complete:
AssociatedObject.Background = //restore color here;
if (effects == DragDropEffects.None)
{
// nothing was dragged
}
else
{
// inspect operation result here
}
}
}
I got a problam with my WP8.1 application. I have a listView and when I tap on item, it get me to a new page with détails but then when I go back to my listView, I can retap the same item but it don't get me anywhere.
Here is my listView SelectionChanged Handler in MainPage.xaml.cs.
private void lvNom_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Person personneSelect = (Person)lvNom.SelectedItem;
Frame.Navigate(typeof(DetailPersonne), personneSelect);
}
Here is the code behind the page I need to show in DetailPersonne.xaml.cs
public sealed partial class DetailPersonne : Page
{
public Person person;
public DetailPersonne()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
person = e.Parameter as Person;
if(string.IsNullOrEmpty(person.Nom) == true){
tbNom.Text = "Non renseigné.";
}
else{
tbNom.Text = person.Nom;
}
if (string.IsNullOrEmpty(person.Prenom) == true)
{
tbPrenom.Text = "Non renseigné.";
}
else{
tbPrenom.Text = person.Prenom;
}
the only navigation change I've done is handling the hardware back button in my App.xaml.cs
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if(rootFrame != null && rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
So if anyone got a fix for that it'll be nice ! Thanks in advance ! :)
try resetting the selected item as SelectionChanged is not firing because the Selection hasnt changed when you navigate back.
private void lvNom_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(lvNom.SelectedItem != null)
{
Person personneSelect = (Person)lvNom.SelectedItem;
lvNom.SelectedItem = null;
Frame.Navigate(typeof(DetailPersonne), personneSelect);
}
}
I am trying to implement a horizontal swipe event handler in the following app. However, the gr_CrossSliding cross sliding event handler never fires.
What do I need to do to fire gr_CrossSliding?
public sealed partial class MainPage : Page
{
private GestureRecognizer gr;
public MainPage()
{
this.InitializeComponent();
gr = new GestureRecognizer();
gr.GestureSettings = GestureSettings.CrossSlide;
gr.CrossSlideHorizontally = true;
gr.CrossSliding += gr_CrossSliding;
}
void gr_CrossSliding(GestureRecognizer sender, CrossSlidingEventArgs args)
{
// handle swipe event
}
}
You need to set the GestureRecognizer on the handlers of the UI Element that is getting the gestures.
In this case, I'm using a Grid (GrdFoto).
public MainPage()
{
this.InitializeComponent();
gestureRecognizer.GestureSettings = Windows.UI.Input.GestureSettings.Drag;
gestureRecognizer.Dragging += gestureRecognizer_Dragging;
GrdFoto.PointerPressed += GrdFoto_PointerPressed;
GrdFoto.PointerMoved += GrdFoto_PointerMoved;
GrdFoto.PointerReleased += GrdFoto_PointerReleased;
GrdFoto.PointerCanceled += GrdFoto_PointerCanceled;
}
void GrdFoto_PointerPressed(object sender, PointerRoutedEventArgs e)
{
this.gestureRecognizer.ProcessDownEvent(e.GetCurrentPoint(this.GrdFoto));
this.GrdFoto.CapturePointer(e.Pointer);
e.Handled = true;
}
void GrdFoto_PointerMoved(object sender, PointerRoutedEventArgs e)
{
this.gestureRecognizer.ProcessMoveEvents(e.GetIntermediatePoints(this.GrdFoto));
}
void GrdFoto_PointerReleased(object sender, PointerRoutedEventArgs e)
{
this.gestureRecognizer.ProcessUpEvent(e.GetCurrentPoint(this.GrdFoto));
e.Handled = true;
}
void GrdFoto_PointerCanceled(object sender, PointerRoutedEventArgs e)
{
this.gestureRecognizer.CompleteGesture();
e.Handled = true;
}
void gestureRecognizer_Dragging(GestureRecognizer sender, DraggingEventArgs args)
{
// Drag completed.
}