Handle button click in Xamarin Forms Android to Navigate to new page - android-activity

I am trying a simple Android app using Xamarin Forms with C# for the coding. In my Main.axml there's a button, on clicking which I'd like to go to a new page, say XInfo.axml.
Now this is my MainActivity.cs:
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Xamarin.Forms;
namespace AlberoPizza
{
[Activity(Label = "Albero Pizza", MainLauncher = true, Icon="#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button btn = FindViewById<Button>(Resource.Id.MyButton);
btn.Clicked += (object sender, EventArgs e) => {
};
}
}
}
Now, I am finding it difficult to structure code inside my Lambda which would handle the navigation to the page, whose name I mentioned. There is no Navigation Bar and there cannot be any navigation bar. Also, for the existing code block, I am getting this error, which is quite weird to me:
Error CS0311: The type 'Xamarin.Forms.Button' cannot be used as type parameter 'T' in the generic type or method 'Android.App.Activity.FindViewById(int)'. There is no implicit reference conversion from 'Xamarin.Forms.Button' to 'Android.Views.View'. (CS0311) (AlberoPizza)
I thought this is how we usually find controls in Android app Xamarin. Can you help me complete the code for this? I'm sure it's a pretty basic type of scenario. There is this persistent error on the one hand and the code to navigate to XInfo.axml on the other. I've tried stuff like Activator.CreateInstance, the PushAsync, etc. inside the lambda, but more errors show up and entire thing becomes more and more complicated.

Related

NavigationPage won't reappear

(Sorry if this question is stupid or has already been asked before)
I'm pretty new to .NET MAUI and I'm trying to build an app and I have this code:
private async void BtnOptionsClicked(object sender, EventArgs e)
{
OptionsPage optPage = new();
NavigationPage navPage = new(optPage)
{
Title = optPage.Title
};
navPage.ToolbarItems.Add(new ToolbarItem("BackButtonPlaceholder", "", async () =>
{
System.Diagnostics.Debug.WriteLine("Back button pressed");
await Navigation.PopAsync();
}));
await Navigation.PushAsync(navPage);
}
I'm trying to add a back button for a specific page, not the MainPage
The problem is that the NavigationPage appears the first time and works, but the second time around it just doesn't show up, only the OptionsPage does
Btw it works fine on Android, just not Windows (I can't test on other platforms)
I tried using RemovePage instead of PopAsync and I tried adding the ToolbarItem in the OptionsPage class, nothing I tried works...
You are mixing Shell and NavigationPage, by default a .NET MAUI project is created with a Shell.
NavigationPage is hierarchicall (you push / pop pages on a stack), it's simpler to use and is more flexible but you have manage everything yourself (like menus for exemple).
Shell is URI-based navigation (work the same as a website pages with urls like "/users/1/profile"), it comes with pre designed menu (tabs and flyout) and make it possible to navigate to absolute URL (which is not easy with NavigationPage). It is "replacing" NavigationPage since it cover a lot of use cases and remove a lot of boilerplate code related to navigation (that's why it's the default).
Since Shell is based on NavigationPage using the NavigationPage methods with Shell wont do any error, you should not mix them though (they are not meant to be used together).
If you want to use NavigationPage you should modify ./App.xaml.cs:
public partial class App : Application
{
public App()
{
InitializeComponent();
// Replace :
// MainPage = new AppShell();
// By this :
MainPage = new NavigationPage(new MainPage());
}
}
Now you can use Navigation.PushAsync(page);, the page object should inherit ContentPage and not another NavigationPage.
If you want to keep Shell read this and use await Shell.Current.GoToAsync("../../route"); to navigate between page.

.Net MAUI Shell navigating to the previous page is not working

I have a .Net MAUI app that uses Shell TabBar for navigating. Besides navigating to various pages, some tabs should just execute some code without showing any content. As TabBar does not provide such a functionality, I used OnAppearing() method of a dummy empty page, and after my code call
Shell.Current.GoToAsync("..");
to return to the previous page. But for some reason, this does not work, and the empty page is still displayed. If I use some actual page, e.g.
Shell.Current.GoToAsync(nameof("SomePage"));
the navigation works as expected, and SomePage is displayed.
Why doesn't ".." work for me?
Here is the code I use:
public class Page1 : ContentPage
{
protected override void OnAppearing()
{
// Some code I need to execute
Shell.Current.GoToAsync("..");
}
}

CrossUI.Droid.Dialog EntryElement loses focus with text prediction

I'm creating a new Dialog view in Droid platform, using the CrossUI.Droid.Dialog project. I'm also using bindings provided by the MvvmCross Framework.
Here is the code I have in the Droid view, to create and bind the Dialog:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
DroidResources.Initialise(typeof(Resource.Layout));
Root = new RootElement()
{
new Section("Private Configuration")
{
new EntryElement("Name:").Bind(this, "{'Value':{'Path':'Configuration.Name'}}"),
new EntryElement("Description:").Bind(this, "{'Value':{'Path':'Configuration.PrivateDescription'}}"),
new BooleanElement("Active?").Bind(this, "{'Value':{'Path':'Configuration.Active'}}")
},
new Section("Display Configuration")
{
new StringElement("Header Title")
{
Click = (o, e) => GoToHeaderTitleActivity(),
LayoutName = "dialog_rootNavigate"
}
}
};
}
When I run the app, the dialog is shown and the bindings are correct.
The problem I have is when I try to write something in one of the EntryElement, the focus just goes somewhere else... This only happens when I have 'Text Prediction' enabled.
I've checked the sample in Android.Dialog and all seems to work just fine.
I'm using a Galaxy Tab 2 7.0, with ICS 4.0
Does anyone had this problem?
Found the answer!!
Apparently there is a known issue in Android where EditText controls and ListView don't play nice. This is not a problem with MvvmCross or Monodroid.Dialog.
To overcome this (and I'm guessing this is the reason for it's existence?) use the MvxLinearDialogActivity when developing forms using dialog. The issue instantly disappears.
As the comment in the class says:
DialogActivity based on a linear view, this will solve all edittext related focus problems when using elements
suggestions at Focusable EditText inside ListView doesn't help for example

ASP.NET Button Click event does not appear to fire

I'm relatively new to ASP.NET. I have a ASP.NET MVC 2 Web Application project (created in Visual Studio 2010). I added a method to HomeController called Search
public ActionResult Search()
{
return View();
}
and created a corresponding view (web page) called Search.aspx onto which I dropped a button. I double-clicked the button to add a handler for the button click event which sets the text of a TextBox, then built the application.
<script runat="server">
protected void MyButton1_Click(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Undo button clicked");
m_search_text_box.Text = "MyButton1_Click";
}
...
When I click the button in my browser (I tested in Chrome and Internet Explorer), nothing happens. The text box is not updated. Nothing is written to the Output window either. So, it doesn't look like the event is firing. Can anybody offer any suggestions? I'm using Visual Studio 2010 on Windows 7.
Thanks
You are mixing WebForms event handling into an MVC app. MVC does not work like WebForms. Check out the tutorials on MVC2 to help get you started down the right path.
Here's a sample app with step by step tutorials to help get to the basics of MVC down.
ASP.NET MVC doesn't use code behind handlers like that. You use controller actions to respond to requests, and decide how to visually handle them (ie: you can render a view, or return a JSON object, or redirect to another Action etc).
In your instance, if you want to put some text in a textbox after the user has clicked the button, you'd want to put a Submit button in a form, and create a controller action to respond to it:
[HttpPost]
public ActionResult Search()
{
var model = new SearchModel();
model.StatusText = "MyButton1_Click";
return View(model);
}
In your view, you want to use this model, and put its StatusText property value into a textbox:
<%= Html.TextBoxFor(x => x.StatusText) %>
Have a look at the ASP.NET MVC website which has a lot of great getting started tutorials, and the Nerd Dinner tutorial (a free chapter in the book).

How to keep business logic seperate within GWT Composites?

I'm currently building a GWT login screen and I managed to get a basic version of the login structure working.
I created the following pieces:
An entry point class (actually it was given).
A main application screen composite.
A login-screen composite.
I have the following logic in my entry point method:
MyApplication mainWindow = null;
public void onModuleLoad() {
LoginScreen loginScreen = new LoginScreen() {
#Override
public String onLogin(String username, String password) {
boolean passwordWasOk = rpcCheckUsernamePassword(username,password); // mechanism not important for this question
if (passwordWasOk) {
RootPanel.get().remove(0);
mainWindow = new MyApplication();
// Using root layout panel as main window is a layout type composite
RootLayoutPanel.get().add(mainWindow);
return null;
} else {
return "password was incorrect";
}
}
};
RootPanel.get().add(loginScreen);
}
So, I created a method in the LoginScreen composite that is called when the user clicks the 'Sign-In' button. If the onLogin method fails its validation of the username and password, then a narrative can be returned to the login composite so that it can update the user. The login screen will stay on the screen until the user uses a correct username/password combination.
My question is, is this the correct way to use composites? Where should my login logic ideally reside. Is a better alternative to inject some sort of login handler object in the constructor of the composite or via a setter or is the method I used quite normal?
As I'm planning to write quite a lot of code, I want to get the coding style correct from the outset.
Any feedback is greatly appreciated.
Thanks,
For complex projects you'd want to use the Model-View-Presenter (MVP) design pattern. It allows you to separate the rendering logic (views) from the business logic. To get you started, the official documentation has two articles about it plus there's that presentation by Ray Ryan that started the whole GWT + MVP = <3 haze :) After that I'd recommend browsing through MVP related questions on SO and GWT's Google Group.