How to navigate from one page to hubsection on another page? - windows-phone-8

I have two pages in my application: "HubPage" and "SectionPage".
How can I navigate from SectionPage to a given Hubsection programmatically?

Navigate with hub index as parameter
Frame.Navigate(typeof(HubPage), 1)
In your hub page:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var index = (int)e.Parameter;
switch (index)
{
case 0: YourHub.ScrollToSection(Hub1);break;
case 1: YourHub.ScrollToSection(Hub2);break;
}
}

Related

What happens to the values of object in windows phone 8 navigation?

When navigating for one page to another does the value of the objects in the previous pages get lost? As I am navigating from page-1 to page-2 and then in page-2 I am calling a method which is in page-1 the values returned are null.
Why is this happening?
first page:
public Offer qw()
{
return off;
}
NavigationService.Navigate(new Uri("/Page1.xaml" ,UriKind.Relative));
page2:
var ob=obj.qw();
values in ob=null
if you are creating your obj field in your page2 means you are creating a new instance of the page1 so obviously it will differ from previous page.
so if you want to execute thi sfunctionality in page behind means you can do this in your page2
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// NavigationEventArgs returns destination page
Page destinationPage = e.Content as Page2;
if (destinationPage != null)
{
// Change property of destination page
destinationPage.Page1=this;
}
}
This is bad logic for Windows Phone application. If you need to send some object from Page_1 to Page_N you should use PhoneApplicationService, if you send some simple object-type (numbers, strings, bools) you can use NavigationContext.
Sample PhoneApplicationService:
// Page_1 before navigate to Page_N
PhoneApplicationService.Current.State[key] = value; // key(string); value(any object)
// Page_N
object o;
PhoneApplicationService.Current.State.TryGetValue(key, out o)
// then do what you want with you object - o
Sample NavigationContext:
// Page_1 before navigate to Page_N
NavigationService.Navigate(new Uri("/SecondPage.xaml?msg=SomeMessageText", UriKind.Relative));
// Page_N
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string msg = "";
if (NavigationContext.QueryString.TryGetValue("msg", out msg))
string yourMessage = msg;
}
See MSDN:
NavigationContext
PhoneApplicationService and PhoneApplicationService samples

Adding "rate my app" to Web App Template

There's a project called Web App Template (aka WAT - http://wat.codeplex.com/) that allows you to wrap a webapp as a Windows 8 / Windows Phone 8 application. I've done that to an app, now I'm trying to add the "rate my app" feature to it. I don't see where/if I can inject code for this component to be added.
I'm following a guide here: http://developer.nokia.com/community/wiki/Implement_%22Rate_My_App%22_in_under_60_seconds
I'm stuck at Step 5 - where do I add the Event Handler? There is no MainPage.xaml.cs and I don't see any similar files.
I imagine that WAT is calling another library to load a web browser. Is there some way I can inject an Event Handler and method into this library?
I suggest not to prompt the user with 'rate my app' thing in the first opening of the app as user should be given some time to see what the app looks like and how it functions. Therefore, keeping the number of app launches and asking to rate the app after some 5th - 10th launch of app will make more sense. Besides you should check if you already prompted the user to rate your app, if so never prompt again. (Otherwise you will piss them off with 'rate my app' thing)
In order to achieve this, you should at first keep the app launch count in app settings class.
The interface for storing any kind of setting:
public interface ISettingService
{
void Save();
void Save(string key, object value);
bool AddOrUpdateValue(string Key, object value);
bool IsExist(string key);
T Load<T>(string key);
T GetValueOrDefault<T>(string Key, T defaultValue);
}
The rating service class that consumes the above interface to store such count and settings:
public class RatingService
{
private const string IsAppRatedKeyName = "isApprated";
private const string TabViewCountKeyName = "tabViewCount";
private const bool IsAppratedDefault = false;
private const int TabViewCountDefault = 0;
private const int ShowRatingInEveryN = 7;
private readonly ISettingService _settingService;
[Dependency]
public RatingService(ISettingService settingService)
{
_settingService = settingService;
}
public void RateApp()
{
if (_settingService.AddOrUpdateValue(IsAppRatedKeyName, true))
_settingService.Save();
}
public bool IsNeedShowMessage()
{
return (_settingService.GetValueOrDefault(TabViewCountKeyName, TabViewCountDefault)%ShowRatingInEveryN) == 0;
}
public void IncreaseTabViewCount()
{
int tabCount = _settingService.GetValueOrDefault(TabViewCountKeyName, TabViewCountDefault);
if (_settingService.AddOrUpdateValue(TabViewCountKeyName, (tabCount + 1)))
_settingService.Save();
}
public bool IsAppRated()
{
return _settingService.GetValueOrDefault(IsAppRatedKeyName, IsAppratedDefault);
}
}
This is how you will run such functionality and prompt the user to rate the app (if previously not rated) anywhere in your project (mainpage or some other page where user launches some functionality):
private void RunRating()
{
if (!RatingService.IsAppRated() && RatingService.IsNeedShowMessage())
{
MessageBoxResult result = MessageBox.Show("Review the app?", "Would you like to review this awesome app?",
MessageBoxButton.OKCancel);
//show message.
if (result == MessageBoxResult.OK)
{
RatingService.RateApp();
new MarketplaceReviewTask().Show();
}
}
}

Navigate to the same View. Why Loaded and OnNavigatedTo events aren't called?

Im doing a cloud App(like Skydrive) in Windows Phone 8 , each time I navigate to a different folder I need to reload the FolderView.xaml page to display the content of this folder and I need to add the view to the back stack then I will be able to back to the previous path...
From now when I try to reload the FolderView from the FolderView.xaml.cs page, none event is called...
I don't understand why ? And if you have a solution you are welcome ...
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
if (App.ElementSelected != null)
{
BdeskElement FolderChoosen = new BdeskElement();
FolderChoosen = App.ElementSelected;
Gridentete.DataContext = FolderChoosen;
GetFiles(FolderChoosen);
}
}
private async void llsElements_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LongListSelector llselement = null;
listElementCollection.Clear();
if (sender != null)
llselement =(LongListSelector)sender;
if(llselement.SelectedItem!=null)
{
BdeskElement bdelement=(BdeskElement)llselement.SelectedItem;
if (bdelement.TypeElement==BdeskElement.BdeskTypeElement.Folder)
{
App.DocLibSelected = null;
App.ElementSelected = bdelement;
// I navigate to the same view here but nothing happens
NavigationService.Navigate(new Uri("/Views/BDocs/FolderView.xaml", UriKind.RelativeOrAbsolute));
}
}
}
To navigate to the same page with a new instance, you must change the Uri. For example:
NavigationService.Navigate(new Uri(String.Format("/Views/BDocs/FolderView.xaml?id={0}", Guid.NewGuid().ToString()), UriKind.Relative));
You can discard that parameter if you don't want/use it.

Windows Phone link from Tile error

I have a list of theaters and I created a secondary tile from my application to navigate directly to specific theater. I pass the id of the theater in query string :
I load the theaters from a WCF service in the file "MainViewModel.cs"
In my home page, I have a list of theaters and I can navigate to a details page.
But when I want to navigate from the tile, I have an error...
The Tile :
ShellTile.Create(new Uri("/TheaterDetails.xaml?selectedItem=" + theater.idTheater, UriKind.Relative), tile, false);
My TheaterDetails page :
public partial class TheaterDetails : PhoneApplicationPage
{
theater theater = new theater();
public TheaterDetails()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
if (DataContext == null)
{
string selectedIndex = "";
if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
{
int index = int.Parse(selectedIndex);
theater = (from t in App.ViewModel.Theaters
where t.idTheater == index
select t).SingleOrDefault();
DataContext = theater;
....
....
....
The error :
https://dl.dropboxusercontent.com/u/9197067/error.png
Like if the data were not loaded...
Do you have an idea where the problem come from ?
The solution could be easy but I am a beginner... Maybe it's because I load the data asynchronously and the application doesn't wait until it's done...
Thanks
EDIT :
My LoadData() method :
public void LoadData()
{
client.GetTheatersCompleted += new EventHandler<ServiceReference1.GetTheatersCompletedEventArgs>(client_GetTheatersCompleted);
client.GetTheatersAsync();
// Other get methods...
this.IsDataLoaded = true;
}
private void client_GetTheatersCompleted(object sender, ServiceReference1.GetTheatersCompletedEventArgs e)
{
Theaters = e.Result;
}
You should check to see which variable is actually null. In this case it looks to be Theaters (otherwise the error would have thrown earlier).
Since Theaters is populated from a web call it is most likely being called asynchronously, in other words when you return from LoadData() the data is not yet there (it's still waiting for the web call to come back), and is waiting for the web service to return its values.
Possible solutions:
Make LoadData() an async function and then use await LoadData(). This might require a bit of rewriting / refactoring to fit into the async pattern (general introduction to async here, and specific to web calls on Windows Phone here)
A neat way of doing this that doesn't involve hacks (like looping until the data is there) is to raise a custom event when the data is actually populated and then do your Tile navigation processing in that event. There's a basic example here.
So the solution that I found, thanks to Servy in this post : Using async/await with void method
I managed to use async/await to load the data.
I replaced my LoadData() method by :
public static Task<ObservableCollection<theater>> WhenGetTheaters(ServiceClient client)
{
var tcs = new TaskCompletionSource<ObservableCollection<theater>>();
EventHandler<ServiceReference1.GetTheatersCompletedEventArgs> handler = null;
handler = (obj, args) =>
{
tcs.SetResult(args.Result);
client.GetTheatersCompleted -= handler;
};
client.GetTheatersCompleted += handler;
client.GetTheatersAsync();
return tcs.Task;
}
public async Task LoadData()
{
var theatersTask = WhenGetTheaters(client);
Theaters = await theatersTask;
IsDataLoaded = true;
}
And in my page :
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadData();
}

Linq's DataContexts and "Unit of Work" pattern. Is my approach ok?

Following the directions from many articles, I've decided to implement the Unit of work pattern to my Linq2SQL DataContexts in my ASP.Net WebForms Application, but I'm not sure if I'm on the right way.
Here's what I'm accomplishing so far:
1 - On every Request, I catch the Application_AcquireRequestState event (which has access to Session data) in Global.asax and instantiate a new DataContext to bind it to the user's Session:
void Application_AcquireRequestState(object sender, EventArgs e)
{
// Check if the request is for a Page, Page Method or Handler
if (new Regex(#"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
MyCompany.MyDatabaseDataContext myDatabaseDataContext = new MyCompany.MyDatabaseDataContext();
HttpContext.Current.Session["myDatabaseDataContext"] = myDatabaseDataContext;
}
}
2 - Every Data Access Layer Object (DAO) inherits from a base DAO: GenericDAO:
public class GenericDAO
{
private MyDatabaseDataContext _dbMyDatabase;
protected MyDatabaseDataContext dbMyDatabase
{
get
{
if (_dbMyDatabase == null)
_dbMyDatabase = HttpContext.Current.Session["myDatabaseDataContext"] as MyDatabaseDataContext;
return _dbMyDatabase;
}
}
}
3 - So, in every operation, the DAO use the DataContext Property from its parent class:
public class MyTableDAO : GenericDAO
{
public List<MyTable> getAll()
{
return dbMyDatabase.GetTable<MyTable>().ToList();
}
}
Here's my concerns...
First of all, is it ok to store the DataContext in the user's Session? What would be another option? My app has a lot of PageMethods calls, so I'm worried the DTX would be invalidated between their async requests if it is stored in the session.
Do I need to capture the Application_ReleaseRequestState event to Dispose() of the DataContext and remove it from the session?
If I don't need to Dispose of it, in every Application_AcquireRequestState, would it be better to Remove DTX from Session - Create DTX - Store it or just Refresh it?
Also, if I don't need to Dispose of it, what about Connections? Would it handle them automatically or I would need to control them too?
I appreciate your time and help :)
-- EDIT
Here's the code I've reached, following #ivowiblo's suggestion:
Global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
if (new Regex(#"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
MyCompany.MyDatabaseDataContext myDatabaseDataContext = new MyCompany.MyDatabaseDataContext();
HttpContext.Current.Items["myDatabaseDataContext"] = ceabsDataContext;
}
}
void Application_EndRequest(object sender, EventArgs e)
{
if (new Regex(#"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
if (HttpContext.Current.Items["myDatabaseDataContext"] != null)
{
System.Data.Linq.DataContext myDbDtx = HttpContext.Current.Items["myDatabaseDataContext"] as System.Data.Linq.DataContext;
if (myDbDtx != null)
myDbDtx.Dispose();
}
}
}
GenericDAO
public class GenericDAO
{
protected MyDatabaseDataContext dbMyDatabase
{
get
{
return HttpContext.Current.Items["myDatabaseDataContext"] as MyDatabaseDataContext;
}
}
}
Simple as that!
The best approach is to put it on HttpContext.Current.Items, creating the DataContext on RequestBegin and dispose it in RequestEnd. In msdn there's an interesting article about the better management of the DataContext, where it's suggested to have short-time DataContext instances.
This pattern is called Open session in view and was created for using NHibernate in web environments.
You say you are implementing unit-of-work, but by storing it in the cache you do not really stick to that unit-of-work.
My advice is to create a new DataContext for every request and not to cache it anyware.