Pass value from user control (popup) to current page windows phone 7 - windows-phone-7

From Mainpage, I use this to open the user control Login.xaml :
myPopup = new Popup() { IsOpen = true, Child = new Login() };
I want to enter information into the Login user control and pass that value back to Mainpage to process, how can I do this? I know how to use OnNavigateTo and From to pass value to other page but it won't work on this case because the Popup actually lays on top the MainPage, so it does not navigate anywhere.

You need to use events for that:
var login = new Login();
login.Completed += (a, b) =>
{
// retrieve login.Data
// close popup
};
myPopup = new Popup() { IsOpen = true, Child = login };
and login user control:
{
...
public event EventHandler Completed;
void OnCompleted
{
var h = Completed;
if (h!= null) h(this, new EventArgs());
}
}
remember to call OnCompleted() in the login whereever it suits (e.g. OK button handler)

Well, you could just use some global variable. However using globals is very bad design. Better option is using for example Event Aggregator pattern. Read about it here, here or here.

Related

Logout Display alert xamarin.forms

I've been trying to allow a user to confirm logout by using DisplayAlert. If they click "No" it should remain in their profile page else they should be redirected back to the login page. I haven't managed to get this done, if I click Yes or No, both options remain in the profile page
public async void LogoutBtn(object sender, EventArgs e)
{
var answer = await DisplayAlert("Exit", "Do you wan't to exit the App?", "Yes", "No");
if(answer.Equals("Yes"))
{
Settings.FirstName = string.Empty;
Settings.LastName = string.Empty;
Settings.Email = string.Empty;
await Navigation.PushAsync(new MainPage());
}
else
{
App.Current.MainPage = new Profile();
}
}
DisplayAlert returns a boolean (true / false):
var answer = await DisplayAlert("Exit", "Do you wan't to exit the App?", "Yes", "No");
if (answer)
{
// User choose Yes
}
else
{
// User choose No
}
As SushiHangover point out DisplayAlert returns a bool. You should replace it with DisplayActionSheet or stay with it and correct the if.
Your else clause seems to be incorrect.
If the user choose No you should do nothing. Why do you assign a new Profile to the MainPage?
Beside that, it seems that you have problems with navigation in general. Looking at your code, logout will push a page on a top of the executing page. Seems a bit weird. I would recommend to get familiar wit the Navigation topic firs of all:
Official doc
There is a free course on Xamarin University on Navigation

What is the best solution for "reseting" the Authentication stack?

Currently in my application I have two Navigation stacks.
Authentication
Main
My Authentication stack looks like this:
Splash Page
Choose Create or Login Page
Login Page
After that I call:
CoreMethods.SwitchOutRootNavigation(NavigationContext.Main);
This all works fine.
When I call Logout from within the Main stack like this:
CoreMethods.SwitchOutRootNavigation(NavigationContext.Authentication);
I will currently be on "Login Page", but I really want it to be the first page "Splash Page".
Having the Navigation stacks remember the stack history is perfect for all other cases.
Question: What is the best solution for "reseting" the Authentication stack?
What I normally do in my apps is following.
I have IAuthenticationService which has a State property, which can be LoggedIn or LoggedOut. When session state changed due to explicit login, or for instance token expires, I set the State to LoggedOut. Also I fire a broadcast message SessionStateChanged through Messenger, so I can catch this message all around the app, and react correspondingly in UI level, like change screen states and so on.
If need to completely log the user, I mean show login page when State is LoggedOut, which is your case, I do the following. I use Xamarin.Forms, but the approach would be similar if you use native iOS or Android.
In my main App class (the one which derives from Xamarin.Forms.Application) I create a method call UpdateMainPage, something like this
private async void UpdateMainPage()
{
if (_authService.State == SessionState.LoggedIn)
MainPage = new NavigationPage(new RequestPage());
else
MainPage = new NavigationPage(new SignInPage());
}
What happens I just change the root page of the application to SignIn flow or Main flow depending on SessionState. Then in my constructor I do the following.
public FormsApp()
{
InitializeComponent();
_authService = Mvx.Resolve<IAuthenticationService>();
UpdateMainPage();
var messenger = Mvx.Resolve<IMvxMessenger>();
_sessionStateChangedToken = messenger.Subscribe<SessionStateChangedMessage>(HandleSessionStateChanged);
}
What I need to do, I need to setup main page beforehand, then I subscribe to SessionStateChanged event, where I trigger UpdateMainPage
private void HandleSessionStateChanged(SessionStateChangedMessage sessionStateChangedMessage)
{
UpdateMainPage();
}
I used this approach for several apps, and it work perfect for me. Hope this helps
I had the very same problem recently and this is what I did:
Navigation stacks:
public enum NavigationStacks {Authentication, Main}
In the App.xaml.cs:
//Navigation stack when user is authenticated.
var mainPage = FreshPageModelResolver.ResolvePageModel<MainPageModel>();
var mainNavigation = new FreshNavigationContainer(MainPage, NavigationStacks.Main.ToString());
//Navigation stack for when user is not authenticated.
var splashScreenPage= FreshPageModelResolver.ResolvePageModel<SplashScreenPageModel>();
var authenticationNavigation = new FreshNavigationContainer(splashScreenPage, NavigationStacks.Authentication.ToString());
here you can leverage James Montemagno's Settings Plugin
if (Settings.IsUserLoggedIn)
{
MainPage = mainNavigation;
}
else
{
MainPage = authenticationNavigation;
}
So far you had already done the code above. But the idea for the problem is to clear the authentication stack except the root page i.e splash Screen:
public static void PopToStackRoot(NavigationStacks navigationStack)
{
switch (navigationStack)
{
case NavigationStacks.Authentication:
{
var mainPage = FreshPageModelResolver.ResolvePageModel<MainPageModel>();
var mainNavigation = new FreshNavigationContainer(MainPage, NavigationStacks.Main.ToString());
break;
}
case NavigationStacks.Main:
{
var splashScreenPage= FreshPageModelResolver.ResolvePageModel<SplashScreenPageModel>();
var authenticationNavigation = new FreshNavigationContainer(splashScreenPage, NavigationStacks.Authentication.ToString());
break;
}
}
}
And finally here is the code inside Logout command:
private void Logout()
{
Settings.IsUserLoggedIn = false;
NavigationService.PopToStackRoot(NavigationStacks.Authentication);
CoreMethods.SwitchOutRootNavigation(NavigationStacks.Authentication.ToString());
}
I know there may be better and more efficient approaches. But that worked for me.

Xamarin Social post without interface prompt - ShareItemAsync

I'm trying to post directly to facebook/twitter without prompting the user with a UIViewController using the following code:
// 1. Create the service
var facebook = new FacebookService {
ClientId = "<App ID from developers.facebook.com/apps>",
RedirectUrl = new System.Uri ("<Redirect URL from developers.facebook.com/apps>")
};
// 2. Create an item to share
var item = new Item { Text = "Xamarin.Social is the bomb.com." };
item.Links.Add (new Uri ("http://github.com/xamarin/xamarin.social"));
// 3. Present the UI on iOS
var shareController = facebook.GetShareUI (item, result => {
// result lets you know if the user shared the item or canceled
DismissViewController (true, null);
});
PresentViewController (shareController, true, null);
BUT the Xamarin.Social instructions say:
As an alternative to presenting the share UI, you can share items directly using the **ShareItemAsync** method of the service.
https://github.com/xamarin/Xamarin.Social
I can't find any examples or explicit tutorials on how to use this. Can anyone help me on this please?
If you look at the source of Xamarin.Social, internally ShareItemAsync is used anyways to carry out the requests. GetShareUI is just a wrapper around ShareItemAsync.
From the source of ShareViewController (which gets the UI), you can see how they are using ShareItemAsync to carry out the requests. Here's the snippet for you.
try {
service.ShareItemAsync (item, account).ContinueWith (shareTask => {
StopSharing ();
.
.
.
.
.
}, TaskScheduler.FromCurrentSynchronizationContext ());
}
So all you need to do is create the item, get hold of the account and call the method on the service, something like this
var item = new Item { Text = "Xamarin.Social is the bomb.com." };
item.Links.Add (new Uri ("http://github.com/xamarin/xamarin.social"));
var account = facebook.GetAccountsAsync().FirstOrDefault();
facebook.ShareItemAsync(item, account);

How to show different pages when app launches time in windows phone 7?

When app launches time need to show the registration page.once user registered it shouldn't goes to registration page need to go log in page.
How to achieve this?
You can navigate to the start page of a Windows Phone app from code.
Remove the "DefaultTask" entry from the WMAppManifest
Remove the NavigationPage attribute from the "DefaultTask" in WMAppManifest, and in the Launching event of your app use the something like the example below to navigate to the page of choice upon launch.
private void Application_Launching(object sender, LaunchingEventArgs e)
{
if (registered)
{
((App)Application.Current).RootFrame.Navigate(new Uri("/<your start page>.xaml", UriKind.Relative));
}
else
{
((App)Application.Current).RootFrame.Navigate(new Uri("/<your registration page>.xaml", UriKind.Relative));
}
}
You just have to decide how you want to determine that someone already registered.
I guess you haven't put a lot of thought to this, the setup is pretty easy! When a user registers you could set a variable in the settings defining that a user already has registered. When the application starts, evaluate this setting and if the user registered you show the register-page, otherwise the login-page. Example:
//After (succesful) registration
Properties.Settings.Default.HasRegistered = true;
Properties.Settings.Default.Save();
//Check the value
var hasRegistered = Properties.Settings.Default.HasRegistered;
if(hasRegistered)
//show Login
else
//show Registration
You can also use the IsolatedStorageSettings.ApplcationSettings to do this. The code below is just sample code, you'll have to provide validation if the settings already exist on the first startup of the app and set a default value 'false' for the setting if no registration has occured yet.
//After registration
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains("HasRegistered"))
settings["HasRegistered"] = true;
settings.Save();
//Check value
var settings = IsolatedStorageSettings.ApplicationSettings;
if (settings.Contains("HasRegistered"))
{
var registered = bool.Parse(settings["HasRegistered"]);
if(registered)
//show login
else
//show registration
}
Hope this helps!

Multiple ajax get requests of same route but different query string

I have had this for a couple of days now.
I have a simple search form. When form is submitted the server searches for some data from another server and return data to the screen. When the submit completes it gets some javascript from the server based on the results returned from the search. the javascript then makes multiple concurrent jquery get requests, lets say 4, to the asp.net mvc3 webapp.
I have demonstrated that all the get requests fire at the same time in Firebug but when debugging my app with VS the breakpoints only get hit once the previous request completes.
The actions are the same but the querys are different; ie
/Home/Details/040801
/Home/Details/040802
/Home/Details/040803
So these are different URLs and, from what i found out, FF should treat them differently.
So my questions are:
Am I missing something obvious?
Does IIS have some funny blocking on the same route?
Is it a session cache issue? I am locking lock (lockobject){} on writes to the common session variables.
Im not using ViewBag or TempData.
The page load times, even when everything is cached in the Session, are still noticeably synchronous.
Windows Server 2008 R2
Using IIS 7.5
ASP.NET MVC 3
VS2010 Chrome or FF browser
I have my routes set up as follows:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute("Details", "{controller}/{action}/{id}/{booking}", new { id = UrlParameter.Optional, booking = UrlParameter.Optional});
Nothing special there as you can see.
Sample code from one of the blocked routes:
public ActionResult Details(string id, bool booking = false)
{
if (booking)
{
return BookingDetails(id, true);
}
Dictionary<string, FlightDetails> detailDic;
string scenarioInput;
lock (DetailsLock)
{
if (Session["DetailDic"] == null)
{
Session["DetailDic"] = new Dictionary<string, FlightDetails>();
}
detailDic = (Dictionary<string, FlightDetails>)Session["DetailDic"];
}
if (detailDic.ContainsKey(id))
{
return PartialView("Details", detailDic[id]);
}
lock (GuidLock)
{
if (Session["DetailGuids"] == null)
{
Session["DetailGuids"] = new Dictionary<string, string>();
}
scenarioInput = ((Dictionary<string, string>)Session["DetailGuids"])[id];
}
// query results list
string queryText = string.Format("<View><Query><Where><Eq><FieldRef Name=\"Title\" /><Value Type=\"Text\">OUT {0}</Value></Eq></Where></Query></View>", scenarioInput);
ListItemCollection oList;
int counter = 0;
do
{
oList = SharepointHelper.GetListFromSharepoint("ListName", queryText, ClientContext);
counter++;
Thread.Sleep(1000);
} while (oList.Count == 0 && counter <= Timeout);
if (oList.Count == 0)
{
return PartialView("Details", (object)null);
}
var item = oList[0];
FlightDetails flightDetails = CreateFlightDetails(id, scenarioInput, item);
lock (DetailsLock)
{
detailDic.Add(id, flightDetails);
}
return PartialView("Details", flightDetails);
}
when using session object in server-side your async calls wait for session object released by other request. Becuase of this async ajax calls act like sync. You have to use session as readonly in that action.
Add this attribute to action you call if you dont write anything to session.
[SessionState(SessionStateBehavior.ReadOnly)]

Resources