void RecordButton_Click(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri("/RecordAudio.xaml",UriKind.Relative));
}
In the above code , is NavigationService a class or is it an object of type NavigationService ? .
if it is a class . then is Navigate() a static method ?
and
if it is an object . Why have we not instantiated NavigateService class using the new operator ?
From what i know: The NavigationService class "belongs" to the recent page you're on and it is never used "on its own". You use its methods instead, like with navigate. The page gets informed when sth. new is to display.
As #VahidNd said - use F12 (if you use VS). To clarify it's like this:
PhoneApplicationPage (which you use) base class is Page:
public class PhoneApplicationPage : Page
{
// content
}
public class Page : UserControl
{
public NavigationCacheMode NavigationCacheMode { get; internal set; }
public NavigationContext NavigationContext { get; }
public NavigationService NavigationService { get; }
public string Title { get; set; }
protected virtual void OnFragmentNavigation(FragmentNavigationEventArgs e);
protected virtual void OnNavigatedFrom(NavigationEventArgs e);
protected virtual void OnNavigatedTo(NavigationEventArgs e);
protected virtual void OnNavigatingFrom(NavigatingCancelEventArgs e);
}
And you can see that it has a property NavigationService of type NavigationService which is a clss in System.Windows.Navigation.
You can see these dependences when you use this F12 key - just set cursor's position on type/property/what you want, and hit the key.
NavigationService is a non static class and so is its method Navigate. And as the method is non static, you need to create an object of the class. But the class NavigationService gets instantiated automatically when the app is run and gets attached as a property to the Frame object and hence available commonly to all the Page Object in a single frame.
refer
For Understanding The Difference between Page Frame Content and Role of the class NavigationService.
Link to a related question One
Link to a related question Two
Related
I am trying to build an mvvm app using mvvmcross. When I start the app a null reference exception occurs.
this is my codebehind file which uses MvvmCross.WindowsUWP.Views.
public sealed partial class MainView : MvxWindowsPage
{
public MainView()
{
this.InitializeComponent();
MainViewModel = (MainViewModel)ViewModel;
}
public MainViewModel MainViewModel { get; set; }
public PlayersViewModel PlayersViewModel { get; set; } = Mvx.IocConstruct<PlayersViewModel>();
}
This is my app.cs file.
public class App : MvxApplication
{
public override void Initialize()
{
RegisterAppStart<MainViewModel>();
}
}
When I set an break point at MainViewModel = (MainViewModel)ViewModel; the break point is hit and I can see that the ViewModel property is null. what I am doing wrong? Thanks in advance.
ViewModel property is not yet initialized in the constructor. That's why its value is still null.
You will need to move the assignment to a different method that gets called later, e.g. OnNavigatedTo:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
MainViewModel = (MainViewModel)ViewModel;
}
Even better, instead of assigning ViewModel to your own auto implemented property, rather have the MainViewModel getter perform the cast. Then you don't even need to do the assignment:
public MainViewModel MainViewModel => (MainViewModel)ViewModel;
Unfortunatelly UWP doesn't support generic base classes in XAML, otherwise you could use MvxWindowsPage<MainViewModel> as the base page, not needing to do the cast at all.
In trying to determine why my app (which came into this brave new world based on thte "Blank App" template) isn't working like I would expect (http://stackoverflow.com/questions/14467756/why-would-my-event-handler-not-get-called), I started a new Blank project, and then deleted MainPage and added a new Basic (not Blank) page which I named MainPage in honor of the dearly departed page (and as a nod to tradition and laziness - so I wouldn't have to change the code in app.xaml.cs which navigates to that page).
The Blank app created the original MainPage.xaml.cs like this (auto-generated comment elided):
namespace AsYouWish
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
...I replaced it with a BasicPage (not BlankPage), and it generated this:
namespace AsYouWish
{
public sealed partial class MainPage : AsYouWish.Common.LayoutAwarePage
{
public MainPage()
{
this.InitializeComponent();
}
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
}
protected override void SaveState(Dictionary<String, Object> pageState)
{
}
}
So the Basic Page gets LoadState() and SaveState(), whereas the Blank Page's MainPage had OnNavigatedTo(). Why does the Basic Page not also have an OnNavigatedTo() event? It seems as if every page has the possibility of being navigated to (and from, but that event I can see as more likely being optional/unnecessary).
This is just a matter of the page template that is being used. OnNavigatedTo virtual method is implemented in Page class therefore it can be overriden in any class inherited directly or indirectly from it. The only difference is that the template used for MainPage.xaml.cs already has an empty OnNavigatedTo method in it and the BasicPage template doesn't.
There's nothing stopping you from overriding the method by adding the following code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// add you own code here
}
Just make sure you keep the base.OnNavigatedTo(e) call or you'll lose the functionality that's already implemented in LayoutAwarePage (enabling LoadState/SaveState).
In case you don't know, it's really easy to add overrides to your class in Visual Studio. Just type override and press space and a dropdown will open with all the methods that you can override in your class. Once you select one of them the complete empty method will be added to your class, just like the one I've included in my answer above.
I have two user controls inside an ASPX page. All I want to do is pass one single int from one control to the other during page load.
I have tried several of the examples on here but none of them work - sorry I mean I can't get them to work! Here's what I've got:
Default.ASPX
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ucBottom.varBottomID = ucTop.varBottomID;
}
}
UCTOP
public partial class ucTop : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
int varBottomID = 100;
}
}
UCBOTTOM
public partial class ucBottom : System.Web.UI.UserControl
{
public int varBottomID { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
BottomText.Text = Convert.ToUInt32(varBottomID).ToString();
}
}
There are no errors except for BottomText.Text returning 0 instead of 100. Also int varBottomID = 100; is stating that it is assigned but never used (ucTop).
From one of the answers here it's good practice for one UC not to be aware of the other and to use the parent to pass data. But alas not for me.
As always, any help would be appreciated (but in a below dummies guide format!).
EDIT - Sorry A typo crept in the code in Default...
In your main page, it's not really changing anything -- it's setting ucBottom.varBottomID to itself. (Edit: appears to have been fixed)
In ucTop, int varBottomID = 100; does nothing -- it sets a variable inside the function, which won't be visible outside.
The result of those two issues is that you never end up having anything communicated from ucTop to ucBottom.
(BTW, convention is to start class names with an uppercase letter, and instance names with a lowercase letter. It's not exactly obvious from looking at the code whether you're attempting to access static or instance members of your classes. From here on i'm assuming you have a ucBottom control, which is an instance of the ucBottom class, and the same for ucTop. It's the only case i see where your code, as pasted, would compile without errors.)
You may need something similar to:
public partial class _Default : Page
{
protected void Page_Load(sender obj, EventArgs e)
{
ucBottom.varBottomID = ucTop.varBottomID; // fix the first issue
}
}
public partial class ucTop : UserControl
{
public int varBottomID { get; set; } // fix the second issue
protected void Page_Load(object src, EventArgs e)
{
varBottomID = 100;
}
}
You will also need to pick different events to trigger on, if you go this route. If everything triggers on Load, you have a problem -- Load fires on the page first, then on the child controls. So the property won't get set correctly. (The setting goes in 3 steps: ucTop deciding the correct value to set, _Default setting it from top to bottom, and ucBottom using it. You need that sequence to go decide, set, use in order for it to work correctly, but if everything triggers on Load you'll end up with set, decide, use or set, use, decide.) You might consider letting _Default do its thing on LoadComplete, and ucBottom on PreRender.
Modify your code as needed.
public partial class ucTop : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
ucBottom.varBottomID = 100;
}
}
public partial class ucBottom : System.Web.UI.UserControl
{
public int varBottomID { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
BottomText.Text = Convert.ToUInt32(varBottomID).ToString();
}
}
Defining a class which both UserControls could access a static variable would work:
public static class RequiredVars
{
public static int BottomID { get; set;}
}
Take the following scenario. I have multiple ASPX pages. Login, Logout, Main, Messages, etc... They all inherit from System.Web.UI.Page of course. For all the pages, I want to override the Render method from the Page class. I could easily copy and paste the same code into each page like so:
protected override void Render(HtmlTextWriter writer)
{
//Code Logic Here
}
But if I had many pages, lets say 20, maintaining the code in each page could get very time consuming and error prone.
That made me think a bit and I thought okay lets try this...override the function in each page but call a static function. That way changing the static function would result in a change for every page. Which works fine... But its not really nice and clean, having to override like that on every single page. Anybody have any ideas or thoughts on this one? Perhaps something simple I am overlooking? Thanks
EDIT: Some pages use the System.Web.UI.Page class and some pages inherit from another class called ModifiedPage which inherits and overridies other functions of the System.Web.UI.Page class. So its not as simple as inheriting all the pages from one class.
EDIT2: All pages need this behavior, some already derive from another class, and I am unable to change the implementation or inheritance hierarchy of that other class.
Instead of inheriting from System.Web.UI.Page, have them all inherit from MyProject.MyBasePage which inherits from Page:
public abstract class MyBasePage : System.Web.UI.Page
{
protected override void Render(HtmlTextWriter writer)
{
//Code Logic Here
}
}
and...
public partial class MySpecificPage : MyBasePage
{
}
Edit
Clarification added to the question now points out the real puzzle - the pages which all need this common Render logic have different inheritance paths. That is more tricky in c#, and you won't be able to avoid at least a little bit of redundant plumbing code. There's plenty of different ways to handle this - here's one approach I have taken in the past:
1) Create an interface for this common functionality. For example, IOverrideRender:
public interface IOverrideRender
{
void Register(OverrideRender render);
}
public delegate void OverrideRender(HtmlTextWriter writer, Action<HtmlTextWriter> original);
2) Each page which needs this functionality gets the interface and wires it like so:
public partial class MyPage : Page, IOverrideRender
{
void IOverrideRender.Register(OverrideRender render)
{
this.overrideRender = render;
}
private OverrideRender overrideRender;
protected override void Render(HtmlTextWriter writer)
{
if(overrideRender != nul)
{
overrideRender(writer, base.Render);
}
else
{
base.Render(writer);
}
}
}
3) In an HttpModule, check to see if the handler is IOverrideRender and if so, pass in your custom render method:
public class OverrideRenderModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += this.HandlePreRequestExecute;
}
private void HandlePreRequestExecute(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
IOverrideRender overridable = app.Context.CurrentHandler as IOverrideRender;
if(overridable != null)
{
overridable.Register(
(writer, original) => {
writer.Write("Hello world"); //custom write
original(writer); //calls base.Render
});
}
}
}
You should create a BasePage which inherits from System.Web.UI.Page. Within the BasePage you could override the Render method and then have all your pages inherit from BasePage.
Add a level in your hierarchy and make a BasePage and do your override there, then inherit all other page from BasePage
I have created a class called BasePage which inherits System.Web.UI.Page. On this page I've declared a property called UserSession which I want to be able to access from any Page/MasterPage.
public class BasePage : System.Web.UI.Page
{
string UserSession { get; set; }
public BasePage()
{
base.PreInit += new EventHandler(BasePage_PreInit);
}
private void BasePage_PreInit(object sender, EventArgs e)
{
UserSession = "12345";
}
}
My Default.aspx.cs page inherits the BasePage class and allows me to access the UserSession property as expected.
public partial class Default : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(UserSession);
}
}
However, even though Default.aspx has MasterPage.Master assigned correctly, when I try and access the UserSession property from MasterPage.Master.cs it can't find it and won't build.
So what am I trying to achieve by doing this? I want to expose a UserSession object to every page in my application. Pretty simple you would have thought? Nope.
MasterPage is separate in the heirarchy to Page so you cannot access the property directly from that. However, MasterPage does have a Page property that returns the Page object, which you can cast to your BasePage class. Then as long as UserSession is public (or internal, or protected internal, which might make good sense here) it can access that property. Unless you've only one master page codebehind, you may want to similarly create a BaseMasterPage and do something like:
public BaseMasterPage : MasterPage
{
protected string UserSession
{
get
{
return (Page as BasePage).UserSession;
}
set
{
(Page as BasePage).UserSession = value;
}
}
}
It is simple. Declare your string variable as public.
EDIT: TheGeekYouNeed's answer is correct... I should know better than to try to answer questions this early on a Monday.
I think you'll need to create a base master page class which holds your UserSession property. This would allow you to access the property from the masterpage as well as the pages that inherit from it.