How do I get access to the QueryString in Windows Phone 7 from a user control - windows-phone-7

I have a simple user control in Windows Phone 7 and I want to get access to the querystring collection from the user controls Constructor. I have tried many ways and cannot seem to get acess to the containing XAML's querystring collection.
Essentially I am navigating to the page and the my user control is going to access the querystring value to write the value back to the interface.
Am I missing adding an assembly or reference or something?

I am not sure you should be trying to get at the information from the page's constructor, as it won't necessairly get called every time you land on this page. A better approach is to override the OnNavigatedTo method inherited from PhoneApplicationPage. Looking a little more carefully at your question, you may be trying to do this within a control embedded in the page, in which case you need to get at the Page in order to obtain the navigation information.
Regardless, the NavigationContext property from the page has a QueryString parameter that you can use to access the information you're after.
The following example assumes I have a parameter named "Message" in the query string when navigating to this page:
public partial class MyPage : PhoneApplicationPage
{
// Constructor
public MyPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
String navigationMessage;
if (NavigationContext.QueryString.TryGetValue("Message", out navigationMessage))
{
this.textBlock1.Text = navigationMessage;
}
}
}

Sorry about that - I started to get there, and thanks for the clarification. Your best bet then is to walk up the visual tree from your control to find the Page, then you can have at the NavigationContext. In my sample below, I have a button on a custom control within the page, whose click event finds the nav context and looks for a certain navigation parameter - I couldn't tell from the question or your follow-up what would drive the control to "want" to find the content of the query string.
(Note about getting info from the ctor follows the code below)
public partial class WindowsPhoneControl1 : UserControl
{
public WindowsPhoneControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
GetTheQueryString();
}
private void GetTheQueryString()
{
var result = "No Joy";
var page = FindRootPage(this);
if (page != null)
{
if (page.NavigationContext.QueryString.ContainsKey("Param"))
{
result = page.NavigationContext.QueryString["Param"];
}
}
queryStringText.Text = result;
}
private static PhoneApplicationPage FindRootPage(FrameworkElement item)
{
if (item != null && !(item is PhoneApplicationPage))
{
item = FindRootPage(item.Parent as FrameworkElement);
}
return item as PhoneApplicationPage;
}
}
Note that this won't work from the ctor because of how Xaml works...the Xml tag drives the ctor to be called, then properties are set as indicated, then it is added as a child/item/etc in its container. If you do need to get at the context ASAP using this "walk up the tree" technique, handle the Control's Loaded event, by which time the control does have a parent and a tree that can be walked...
public WindowsPhoneControl1()
{
InitializeComponent();
Loaded += WindowsPhoneControl1_Loaded;
}
private void WindowsPhoneControl1_Loaded(Object sender, RoutedEventArgs e)
{
GetTheQueryString();
}

I would add a property to the UserControl subclass that would be set by the page in its OnNavigatedTo() method.

Related

Xamarin MVVM Databinding not refreshing

i am struggling with the mvvm data binding. I am not using any framework for the mvvm, I got a very basic base class for my view models. I uploaded my example-app with my problem to GitHub, find the link below.
My problem:
I got a simple app with an tab menu. there are 2 tabs called "TabA" and "TabB". Both views have a simple view model. The view models are referencing a manager class which holds the data. The Manager class has to objects (objects of my datamodel-class which just contains a string and implements INotifyPropertyChanged) in an observablecollection. There is also a Property in the Manager which references the current choosen object (its just one of the 2 objects from the list).
There are 2 actions which can be done by "TabB". The first one works as expected. If you enter some new string into the entry an hit the first button, it updates the string of the current choosen object and updates the label in TabA.
What is not working? With the second Button in my "TabB" class you switch the value of the current choosen object in the Manager. In the debugger I can see that the value is changed, but the Label in "TabA" does not recognize that it has to update the value.
Can you help me?
https://github.com/dercdev/MVVM-Xamarin
With the help of Jason I came to something like this:
In my TabAViewModel I subscribed the event of the Manager:
public TabAViewModel()
{
_mgr = Manager.Instance;
_mgr.PropertyChanged += new PropertyChangedEventHandler(obj_PropertyChanged);
}
Then I raise the event:
private void obj_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged("CurrentData");
}
Which updates the label of the view.
Is that okay or is there a "better" way to do it?
As far as I know, the better way is to use INotifyPropertyChanged. If you want to implement Notify, I think you need to implement INotifyPropertyChanged interface, you can create one class name ViewModelBase that inheriting INotifyPropertyChanged, like this:
public class ViewModelBase:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Then you can call RaisePropertyChanged method to inotify when property changed,
private string _text;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
RaisePropertyChanged("Text");
}
}
ObservableCollection implements INotifyPropertyChanged, allowing the collection to notify the user when the contents of the collection have changed - and specifically, what changed within the collection. For example, if you add an item to the collection, the CollectionChanged event will be raised with properties that tell you the index of the new item as well as including the item in a list.
So ObservableCollection _list don't need to call RaisePropertyChanged method.
https://learn.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1.system-componentmodel-inotifypropertychanged-propertychanged?view=netframework-4.7.2

windows phone 7 how to pass Array value from one scree to another screen

///first I have crated Popular class for storing values
public class Popular
{
public string trk_mnetid,trk_title , art_mnetid, art_name, image_url;
}
/// create popularplaylist class
public partial class PopularPlaylist : PhoneApplicationPage
{
Popular popobj = new Popular();
List<Popular> pop = new List<Popular>();
/* call json parsing it and show only "titles" in List form when i m click on perticular title i need to show details in next screen which i paser and store in popular popularplaylist class.
i use navigationservice call new screen
*/
NavigationService.Navigate(new Uri("/Popular_Module/PopularPlaylist.xaml", System.UriKind.Relative));
}
// plz tell me how to get list data in next screen
Use querystring.
Passing Value: In MainPage.xaml.cs add the following
The easiest way to pass a parameter is just to use a string, something like:
private void btnNavigate_Click(object sender, RoutedEventArgs e)
{
string url=String.Format("/Page1.xaml?parameter={0}",popular);
NavigationService.Navigate(new Uri(url, UriKind.Relative));
}
Getting Value: In Page.xaml.cs add the following
Note: It is important to override the OnNavigatedTo and after that you can use the NavigationContext to get the passed parameter.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
List<string> parameterValue = NavigationContext.QueryString["parameter"];
}
Another popular syntax to get the value of the parameter is:
List<string> parameter = string.Empty;
if (NavigationContext.QueryString.TryGetValue("parameter", out parameter))
{
//do something with the parameter
}

Get NullReferenceException on page load while get NavigationContext.QueryString

I used the MVVM pattern to develop my Windows app. When the user click on the item on my listbox usercontrol. The code behind of the viewmodel will navigate the another page. The page is shown correctly, but the problem is I got an error -" NullReferenceException" when I want to get the queryString from Navigation context. I checked the uri on my viewmodel is corrected. Would some one show me how to make it work? Thanks in advance.
I reference at An error is occur when we use navigation to move other page to add the following code on App.xamls.cs page, so the viewModel page can navigate another page.
public static PhoneApplicationFrame CurrentRootVisual
{
get
{
return (App.Current.RootVisual as PhoneApplicationFrame);
}
}
public static bool Navigate(Uri source)
{
if (CurrentRootVisual != null)
return CurrentRootVisual.Navigate(source);
return false;
}
public static void GoBack()
{
if (CurrentRootVisual != null)
CurrentRootVisual.GoBack();
}
There is code on viewModel to navigate the page:
private void ShowCallPage()
{
if (m_CurrentQueue != null)
App.Navigate(new Uri("/PivotPage1.xaml?id=" + m_CurrentQueue.callNumber, UriKind.Relative));
}
There is the code I get error on the another page:
public PivotPage1()
{
InitializeComponent();
MessageBox.Show(NavigationContext.QueryString.ContainsKey("id").ToString());
}
Don't access the NavigationContext object on the PivotPage1 constructor, use the Loaded event instead.

mvvmlight - what's the "proper way" of picking up url parameters for a view model

I'm just switching a project across to mvvmlight and trying to do things "the right way"
I've got a simple app with a listbox
When an item is selected in the listbox, then I've hooked up a RelayCommand
This RelayCommand causes a call on an INavigationService (http://geekswithblogs.net/lbugnion/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx) which navigates to a url like "/DetailPage.xaml?DetailId=12"
The DetailPage.xaml is then loaded and ... this is where I'm a bit unsure...
how should the DetailPage get hooked up to a DetailView with DetailId of 12?
should I do this in Xaml somehow using a property on the ViewLocator?
should I do this in the NavigatedTo method?
Please feel free to point me to a full sample - sure this has been done a (hundred) thousand times before, but all the blogs and tutorials seem to be skipping this last trivial detail (focussing instead on the messaging and on the ioc on on the navigationservice)
Thanks!
The only place you can retrieve the URL parameter is in the view. So since your view is likely depending on it, you should fetch it in the OnNavigatedTo method.
Then, you should pass it along to your viewmodel, either using messaging (to expensive if you ask me), or by referring to your datacontext (which is the viewmodel I presume), and execeuting a method on that.
private AddTilePageViewModel ViewModel
{
get
{
return DataContext as AddTilePageViewModel;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var postalCode = NavigationContext.TryGetKey("PostalCode");
var country = NavigationContext.TryGetStringKey("Country");
if (postalCode.HasValue && string.IsNullOrEmpty(country) == false)
{
ViewModel.LoadCity(postalCode.Value, country);
}
base.OnNavigatedTo(e);
}
I'm using some special extensions for the NavigationContext to make it easier.
namespace System.Windows.Navigation
{
public static class NavigationExtensions
{
public static int? TryGetKey(this NavigationContext source, string key)
{
if (source.QueryString.ContainsKey(key))
{
string value = source.QueryString[key];
int result = 0;
if (int.TryParse(value, out result))
{
return result;
}
}
return null;
}
public static string TryGetStringKey(this NavigationContext source, string key)
{
if (source.QueryString.ContainsKey(key))
{
return source.QueryString[key];
}
return null;
}
}
}
Create a new WindowsPhoneDataBound application, it has an example of how to handle navigation between views. Basically you handle the navigation part in your view, then set the view's DataContext accord to the query string. I think it plays nicely with the MVVM pattern since your ViewModels don't have to know anything about navigation (which IMO should be handled at the UI level).

wicket - Implement Ajax add/remove items ListView

Im getting crazy about this issue. I implemented a ListView which you can add/remove TextField dinamically, but only the last TextField is removed.
An example:
// Object type which is used in the list
public class ExampleObject implements Serializable{
private String keyword;
public String getKeyword() {
return this.keyword;
}
public void setKeyword(String s) {
keyword = s;
}
}
//ListView
List<ExampleObject> keywordList = new ArrayList<ExampleObject>();
keywordList.add(new ExampleObject());
ListView keywordView = new ListView("keywordView", keywordList) {
#Override
protected void populateItem(final ListItem item) {
ExampleObject model = (ExampleObject) item.getModelObject();
item.add(new TextField("subKeyword", new PropertyModel(model, "keyword")));
// keyword remove link
AjaxSubmitLink removeKeyword = new AjaxSubmitLink("removeKeyword", myForm)
{
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
ExampleObject selected = (ExampleObject) item.getModelObject();
// I also tried deleting by index. println shows the
// selected object is the element I want to remove, so why always
// remove last object of the list?
keywordList.remove(selected);
if (target != null) {
target.addComponent(myForm);
}
}
};
item.add(removeKeyword);
// keyword add link
AjaxSubmitLink addKeyword = new AjaxSubmitLink("addKeyword", metadataForm)
{
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
keywordList.add(new ExampleObject());
if (target != null) {
target.addComponent(myForm);
}
}
};
item.add(addKeyword);
}
keywordView.setReuseItems(true);
metadataForm.add(keywordView);
Any help would be very appreciate, because I thing this issue is really a very stupid mistake but I cant get it!
Thanks
It might be as simple as getting rid of the line
keywordView.setReuseItems(true);
The reuseItems flag is an efficiency so that the page does not rebuild the ListView items unnecessarily, but it can lead to confusion such as what you're seeing.
ListView really wasn't made for use with forms though, and you'll probably be better off with another tactic entirely.
This blog entry on building a list editor form component might be useful. It will need some changes if you're not on Wicket 1.4, but similar stuff is definitely possible in Wicket 1.3, and the comments have some hints.
Read the javadoc of ListView#setReuseItems():
"But if you modify the listView model object, than you must manually call listView.removeAll() in order to rebuild the ListItems."
You can not use a ListView this way. Either use the members of ListView provided:
removeLink(java.lang.String id, ListItem<T> item)
and
newItem(int index)
but, I never used those. If I have to display a List and be able to add remove Items dynamically, I prefer the RefreshingView.
If you do use FormComponents inside a RefreshingView, make sure you set a Reusestartegy (setItemReuseStrategy())
Bert

Resources