I'm creating a messaging app, and I need that when I enter the messaging thread with someone, message bubbles show inside the layout. I'm doing this easily using:
MyMessageThreadStackLayout.Children.Add(
// Message bubble building logic goes here
);
But currently, I'm putting this inside the:
protected override void OnAppearing ()
But this makes my elements appear after the content page animation is shown making it look really weird. Is there a OnCreate event that can let me load the messages into the view before showing them with the animation? Thank you
You could use the protected virtual void LayoutChildren method that's exposed on all Pages. Keep in mind it may be called many times, so you'll need to account for that possibility.
Another option would be to simply add your child Views in the Page's constructor. This option is not ideal, but it's guaranteed to only be called once, and always before your Page is presented.
Related
Does anyone know a source for an overview of the Caliburn.Micro Screen/Conductor Lifecycle? For example a sequence diagram / flow chart that describes their call order/dependencies and the conditions when they get called or not?
Until now I have primarily uses OnViewLoaded but I want to know which are called a second time (when shown again) etc. I didn't found a good documentation about the Screen Lifecycle yet.
And yes, I know it is Open Source and I can read the source code or debug that (what I'm doing at the moment)... just thought that this requirement is somewhat basic to work with Caliburn.Micro and there must be something already done and I don't need to create that overview on my own. Maybe the answer might help someone else, too. ;-)
For example, when derriving from Conductor.Collection.OneActive
there are the following (and even more) methods that seem to play a role in the lifecycle and can be overloaded:
protected virtual void OnInitialize()
protected virtual void OnActivate()
protected virtual void OnActivationProcessed(IScreen item, bool success)
protected virtual void OnDeactivate(bool close)
protected virtual void OnViewAttached(object view, object context)
protected virtual void OnViewLoaded(object view)
protected virtual void OnViewReady(object view)
What I have seen so far this seems to be the order (app startup to exit):
OnViewAttached
OnInitialize
OnActivate
OnViewReady
OnViewLoaded
OnActivationProcessed
OnDeactivate
But what are the bullet points for each method? E.g. when is the datacontext set, the style template applied to the view and ready to be shown? When is the view shown? (difference between ViewReady and ViewLoaded?)
Not a full answer but it is a start, from the documentation of this project, which is worth reading, you can find bullet points for some of those events:
OnInitialize – Override this method to add logic which should execute only the first time that the screen is activated. After initialization is complete, IsInitialized will be true.
OnActivate – Override this method to add logic which should execute every time the screen is activated. After activation is complete, IsActive will be true.
OnDeactivate – Override this method to add custom logic which should be executed whenever the screen is deactivated or closed. The bool property will indicated if the deactivation is actually a close. After deactivation is complete, IsActive will be false.
OnViewLoaded – Since Screen implements IViewAware, it takes this as an opportunity to let you know when your view’s Loaded event is fired. Use this if you are following a SupervisingController or PassiveView style and you need to work with the view. This is also a place to put view model logic which may be dependent on the presence of a view even though you may not be working with the view directly.
There is also a good explanation on the parameters being sent to the methods, and many other topics for the layers of the screens and their life cycle.
I programming a WPF GUI that uses multiple Views. I am using the MVVM Light Toolkit to implement the MVVM pattern.
For Navigating i use this mechanism by changing my main frame to a NavigationWindow and all my views to Pages.
I injected the navigation service in the ViewModel constructor and now I can navigate between the views.
However, i would like to transmit data between the views while navigating. There is a method from Navigation Window that makes this possible through event handlers. I already implemented a method into my Interface but I'm having problems calling the event handler on the navigated View Model.
Can anyone tell me how to call the event handler inside my ViewModel?
Thanks!!
Edit: I tried calling:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
}
But i get an error saying:
OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs)': no
suitable method found to override
I already cleaned my solution and tried a rebuild...
Any ideas?
Edit2:
So i found out that in WPF .Net 4.5 the OnNavigatedTo event is gone. What i couldnt find out why and how i could call something similiar.
I haven't gotten an answer to my question so I will attempt an answer...
Don't over think this...if one needs to transfer information either create a static link to the VM(s) in question, or set aside a static drop on the app class. Either way when a view is shown, subscribe to one of the initialization/load events and pick up the information at the predetermined location.
I have an application for Windows 8 with a page (Frame) for displaying a list of items and a page for downloading & displaying the items details. I am also using MVVM Light for sending notifications.
Application use goes something like this:
Open Main Page
Navigate to List Page
Frame.Navigate(typeof(MyPage));
Choose Item
//Complete logic
Frame.GoBack();
Back on Main Page, I start downloading the file in the view model, I send ONE NotificationMessage saying BeginDownloadFile and after it is downloaded ONE NotificationMessage saying EndDownloadFile.
The first time I do steps 2,3, & 4 my NotificationReceived method is hit once, the second twice and so forth.
private async void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == Notifications.BeginDownloadFile)
{
FileDownloadPopup.IsOpen = true;
}
else if (msg.Notification == Notifications.EndDownloadFile)
{
FileDownloadPopup.IsOpen = false;
}
}
Additional information: I only have one FileDownloadPopup, yet each time, an additional popup is shown each time the NotificationMessageReceived method is called.
My only conclusion is that between navigating forwards and backwards in my app, there are multiple MainPages being created and never closed. This results in many NotificationsMessageReceived methods just waiting for a notification to come their way so they can show their popup.
I have two questions:
1. Does this sound like normal behaviour for a Windows 8 app?
2. How can I close all instances of the MainPage or return to the previous instance without creating a new instance?
Please let me know if I have missed something important out before marking my question down.
This sounds normal to me. The default navigation behaviour in Windows 8 is to create a new page instance each time you navigate to a new page, regardless of whether this is forward or back navigation.
Try setting the NavigatinCacheMode on MainPage to Required. See the MSDN documentation for details of how page caching works.
It sounds like you are registering eventhandlers in the page and then not removing them. Each time you navigate to the page again the handler is being added again in addition to the one you previously added. Try to add your event handler in OnNavigatedTo, and make sure you unregister it in OnNavigatedFrom.
protected override void OnNavigatedTo(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
MyEvent.OnDownloadRequest += MyLocalDOwnloadHandler; // add the handler
}
protected override void OnNavigatedFrom(Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
MyEvent.OnDownloadRequest -= MyLocalDOwnloadHandler; // remove the handler
}
Hi I just found out that my application was crashing when returning from tombstoning. I was able to target the problem here inside the constructor of my page:
RadPhoneApplicationFrame frame = App.Current.RootVisual as RadPhoneApplicationFrame;
frame.PageTransitionCompleted +=
new EventHandler<EventArgs>(frame_PageTransitionCompleted);
Everytime the app is Re-Activated the RootVisual is setting the frame to null. I'm wondering if there is a casting issue here because before I used this code my tombstoning was working perfectly and I was able to navigate freely throughout the app. Any ideas on what might be causing this? Or maybe a work around?
You should move this code from page constructor to OnNavigatedTo method override in your page. Reason is that RootVisual is probably set in RootFrame.Navigated event handler which is generated after page is constructed, not before (this depends of implementation in your App.xaml.cs).
Of course because OnNavigatedTo method may be runned more that once for a page, you should make sure that PageTransitionCompleted event handler is not assigned two times (just use -= before +=).
Another option is to move this code to App.xaml.cs. This makes sense most to me, because that PageTransitionCompleted event is related to whole app, not a single page.
I'm working on an ASP.NET project in which the vast majority of the forms are generated dynamically at run time (form definitions are stored in a DB for customizability). Therefore, I have to dynamically create and add my controls to the Page every time OnLoad fires, regardless of IsPostBack. This has been working just fine and .NET takes care of managing ViewState for these controls.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
RenderDynamicControls()
}
private void RenderDynamicControls()
{
//1. call service layer to retrieve form definition
//2. create and add controls to page container
}
I have a new requirement in which if a user clicks on a given button (this button is created at design time) the page should be re-rendered in a slightly different way. So in addition to the code that executes in OnLoad (i.e. RenderDynamicControls()), I have this code:
protected void MyButton_Click(object sender, EventArgs e)
{
RenderDynamicControlsALittleDifferently()
}
private void RenderDynamicControlsALittleDifferently()
{
//1. clear all controls from the page container added in RenderDynamicControls()
//2. call service layer to retrieve form definition
//3. create and add controls to page container
}
My question is, is this really the only way to accomplish what I'm after? It seems beyond hacky to effectively render the form twice simply to respond to a button click. I gather from my research that this is simply how the page-lifecycle works in ASP.NET: Namely, that OnLoad must fire on every Postback before child events are invoked. Still, it's worthwhile to check with the SO community before having to drink the kool-aid.
On a related note, once I get this feature completed, I'm planning on throwing an UpdatePanel on the page to perform the page updates via Ajax. Any code/advice that make that transition easier would be much appreciated.
From Dirk to Dirk :-)
What do you mean with RenderDynamicControls? Create and set controls? If this is your intention not ASP.NET is managing your ViewState, but you do. If you fill the controls on every load, you always overwrite the existing ViewState!
If you want to use the ViewState, create your controls in the pages init event and fill them in the load event, but only if the request isn’t a postback. This is necessary, because ASP.NET recreates the ViewState between init and load. And this is also the reason for the two “rendering cycles” you describe. You need the first control creation cycle because ASP.NET can’t restore the ViewState without a proper control set and ASP.NET can’t react proper on your response without it.
Back to your code: In general your RenderDynamicControlsALittleDifferently wouldn’t work - because you create your controls too late in the pages life cycle and you would damage the ViewState by inserting new objects to the control collection. In a similar situation I solved this problem by a redirecting the page to itself (Response.Redirect). In this case RenderDynamicControls would do the job, based on a “little differently situation” after you change your internal state.