I am trying to prevent the user of my app from pressing the hardware back button.
I have found this code snippet that is in the code behind the xaml file:
protected override bool OnBackButtonPressed()
{
return true;
}
I have tried variations of this including using Boolean instead of Bool and returning base.functionname nothing seems to fire this method.
Here is the bigger context:
Code behind:
namespace Watson.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class StartScan : ContentPage
{
public StartScan()
{
InitializeComponent();
}
protected override bool OnBackButtonPressed()
{
return true;
}
}
}
This is the second page in the stack and disabling the button only needs to happen on this page only, no where else.
Any help would be appreciated.
This is working for me, I tried in Android and iOS platforms using Xamarin.Forms.
Hope you can resolve with this piece of code.
namespace Test
{
public partial class TestPage2 : ContentPage
{
public TestPage2()
{
NavigationPage.SetHasBackButton(this, false);
InitializeComponent();
}
protected override bool OnBackButtonPressed()
{
//return base.OnBackButtonPressed();
return true;
}
}
}
Thanks,
You can also add NavigationPage.SetHasBackButton property in the XAML
NavigationPage.HasBackButton="True"
In the Content Page
You can do this way:
namespace Watson.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class StartScan : ContentPage
{
public StartScan()
{
NavigationPage.SetHasBackButton(this, false);
InitializeComponent();
}
protected override bool OnBackButtonPressed()
{
// you can put some actions here (for example, an dialog prompt, ...)
return true;
}
}
}
For me it is working with the following code (Samsung Android)
protected override bool OnBackButtonPressed()
{
//base.OnBackButtonPressed();
browser.GoBack();
return true;
}
OnBackButtonPressed firing when you click the back button on your device, not from your navigation page, do your logic in OnDisappearing!
Related
I'm working with C# xamarin forms android and I'm trying to close my sidebar when the user touches de backbuttom but I'm not able to do it. Instead, my aplications closeses.
HomePage.xaml.cs code:
public partial class HomePage : ContentPage
{
string[] subs;
public HomePage()
{
//NavigationPage.SetHasBackButton(this, false);
InitializeComponent();
}
protected override bool OnBackButtonPressed()
{
return true;
}
}
my sidebar AppShell.xaml.cs code:
public partial class AppShell : Xamarin.Forms.Shell
{
public AppShell()
{
InitializeComponent();
nameuser.Title = Preferences.Get("displayName", "Default");
versionadoAPP.Text = "v" + $"{VersionTracking.CurrentBuild}.{VersionTracking.CurrentVersion}";
}
protected override bool OnBackButtonPressed()
{
return true;
}
}
Image of my app:
How could I resolve that?
Thank tou very much!
The easiest way that do this is to set the flyout presented property.
Try something like this:
Shell.Current.FlyoutIsPresented = false;
Good luck!
I've got a Xamarin.Forms WPF application running, but there is a huge title bar.
I have tried the solution of adding NavigationPage.SetHasNavigationBar(this, false); inside my MainPage class's constructor
Here is the code:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
NavigationPage.SetHasNavigationBar(this, false);
}
}
Still I am getting huge title bar size in WPF application, on the other hand, while running on UWP, it is working fine.
You could try to add below codes in your MainWindow.xaml.cs in wpf project:
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
if (!topBarsRemoved) RemoveTopBars();
}
private bool topBarsRemoved = false;
private void RemoveTopBars()
{
var topAppBar = this.Template.FindName("PART_TopAppBar", this) as FormsAppBar;
if (topAppBar != null)
(topAppBar.Parent as System.Windows.Controls.Grid)?.Children.Remove(topAppBar);
topBarsRemoved = true;
}
I have tabbed page with 4 children(4 tabs), and i want to override back button to allways set first 1 page when you push it. I tried several ways, this seems to make the most sense to me, but it doesn't work - tabbedPage is always null (when i override in all tabs)
protected override bool OnBackButtonPressed()
{
var tabbedPage = this.Parent as TabbedPage;
tabbedPage.CurrentPage = tabbedPage.Children[1];
return base.OnBackButtonPressed();
}
I tried to override this back button in TabbedPage Parent like this:
protected override bool OnBackButtonPressed()
{
if(CurrentPage == FirstPage)
{
return base.OnBackButtonPressed();
}
CurrentPage = FirstPage;
return true;
}
but it always close my app. Any idea why that tabbedPage is null for me?
My problem was that my children page is NavigationPage and I should use this.Parent.Parent to cast. So this is how it should be done when u use NavigaionPage as Children of TabbedPage
protected override bool OnBackButtonPressed()
{
var tabbedPage = this.Parent.Parent as TabbedPage;
tabbedPage.CurrentPage = tabbedPage.Children[0];
return true;
}
Firstly, when you have TabbedPage, OnBackButtonPressed is being invoked not in the ContentPage, but instead on the TabbedPage itself. So, the correct place to override the method is in the TabbedPage indeed.
Secondly, if you override the method in the TabbedPage itself, it will do the work, like this:
protected override bool OnBackButtonPressed()
{
var firstPage = Children[0];
if (CurrentPage == firstPage)
{
return base.OnBackButtonPressed();
}
CurrentPage = firstPage;
return true;
}
NB: Be careful what your Children collection is. If you have wrapped your pages in a NavigationPage, the check won't be correct.
You could set the current TabbedPage in App.xaml.cs when set the MainPage of App .
in App.xaml.cs
MainPage here is the TabbedPage in your project.
public partial class App : Application
{
public MainPage CurrentPage { get; }
public App()
{
InitializeComponent();
MainPage tabbedPage = new MainPage();
CurrentPage = tabbedPage;
DependencyService.Register<MockDataStore>();
MainPage = tabbedPage;
}
//...
}
And now you can access it in child page .
protected override bool OnBackButtonPressed()
{
App currentApp = Application.Current as App;
var tabbedpage = currentApp.CurrentPage;
tabbedpage.CurrentPage = tabbedpage.Children[0];
return true;
}
The above code works fine in my project. If it still doesn't work on your side, you could share a sample so that I can test it .
I am trying to build a webview app for one of my projects using Xamarin but I can't seem to figure out how to make the webview element go to previous page instead of closing the app.
So I have figured out how to detect the back button being pressed and prevent it from closing the app but I want to make the web page go back and if the web page can't go back then close the app.
Here's my code at the moment:
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Application = Xamarin.Forms.Application;
namespace myNewApp
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public class WebPage : ContentPage
{
public object _browser { get; private set; }
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
return true;
}
public WebPage()
{
var browser = new Xamarin.Forms.WebView();
browser.Source = "https://myurl.com";
Content = browser;
}
}
}
I have tried a couple of answers and I found this bit of code but it doesn't work as the override can't access the public WebPage browser var:
if (browser.CanGoBack)
{
browser.GoBack();
return true;
}
else
{
base.OnBackButtonPressed();
return true;
}
Any help would be much appreciated.
you need to make browser a class level variable so you can access it anywhere in your page.
public class WebPage : ContentPage
{
Xamarin.Forms.Webview browser;
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
if (browser.CanGoBack)
{
browser.GoBack();
return true;
}
else
{
base.OnBackButtonPressed();
return true;
}
}
public WebPage()
{
browser = new Xamarin.Forms.WebView();
browser.Source = "https://myurl.com";
Content = browser;
}
}
I didn't know how better to word the title so I went with solution that came to my mind.
Here is the problem. I have a page that has list and each item on the lists opens a detail page (on click). But the VM is reused, which causes me several problems.
Previous data can be seen for split second when opening a the detail page
I need certain properties to be set to specific values when the page open, but since the VM is reused it keeps all the values from the previous detail and this messes up my logic.
This UWP app. I'm using Template10 framework's NavigationService to move between pages.
Main Page ViewModel
public class MainPageViewModel : ViewModelBase {
private List<MangaItem> _mangaList;
public List<MangaItem> mangaList {
get { return _mangaList; }
set { Set(ref _mangaList, value); }
}
private string _mainSearchText;
public string mainSearchText {
get { return _mainSearchText; }
set { Set(ref _mainSearchText, value); }
}
public MainPageViewModel() {
_mangaList = new List<MangaItem>();
mangaList = new List<MangaItem>();
Initialize();
}
private async void Initialize() {
mangaList = await MangaListGet.GetListAsync();
}
public async void MainSearchSubmitted() {
mangaList = await MangaListGet.GetListAsync(_mainSearchText);
}
public void MangaSelected(object sender, ItemClickEventArgs e) {
var mangaItem = (MangaItem)e.ClickedItem;
NavigationService.Navigate(typeof(Views.MangaDetail), mangaItem.id);
}
}
And Detail Page ViewModel
class MangaDetailViewModel : ViewModelBase {
private MangaItem _mangaDetail;
public MangaItem mangaDetail {
get { return _mangaDetail; }
set { Set(ref _mangaDetail, value); }
}
private string _mangaId;
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> suspensionState) {
_mangaId = parameter as string;
Initialize();
await Task.CompletedTask;
}
private async void Initialize() {
mangaDetail = await MangaDetailGet.GetAsync(_mangaId);
}
public void ChapterSelected(object sender, ItemClickEventArgs e) {
var _chapterId = (ChapterListItem)e.ClickedItem;
NavigationService.Navigate(typeof(Views.ChapterPage), _chapterId.id);
}
}
This code only shows the first problem is displaying previously loaded data for a split second. If needed I will add code that showcases the other problem, but I' not sure if it's really relevant right now. I'm thinking that maybe my entire logic is flawed or something.
EDIT:
<Page.DataContext>
<vm:ChapterPageViewModel x:Name="ViewModel" />
</Page.DataContext>
where vm is xmlns:vm="using:MangaReader.ViewModels".
Another solution is to use Bootstrapper.ResolveforPage() which is intended to handle dependency injection but would easily serve your needs. Like this:
[Bindable]
sealed partial class App : BootStrapper
{
static ViewModels.DetailPageViewModel _reusedDetailPageViewModel;
public override INavigable ResolveForPage(Page page, NavigationService navigationService)
{
if (page.GetType() == typeof(Views.DetailPage))
{
if (_reusedDetailPageViewModel == null)
{
_reusedDetailPageViewModel = new ViewModels.DetailPageViewModel();
}
return _reusedDetailPageViewModel;
}
else
{
return null;
}
}
}
The NavigationService will treat this the same as any other view-model. Meaning it will call OnNavTo() and the other navigation overrides you include.
Best of luck.
While Template10 documentation states the NavigationCacheMode is disabled by default, that isn't the case in it's example templates (as of writing this). This is set in View C# code (.xaml.cs file).
.xaml.cs file
namespace MangaReader.Views {
public sealed partial class MangaDetail : Page {
public MangaDetail() {
InitializeComponent();
//NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled; //this was set by default
NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Disabled;
}
}
}
Now, new ViewModel will be created each time you access a this page.