I see two basic ways to implement "loading" feedback (e.g. swirly loading icon):
In the presenter:
void displayData()
{
display.startShowingLoadingIcon();
startLoadingData();
}
void onDataLoaded()
{
display.stopShowingLoadingIconAndDisplayData(data);
}
In the display:
void showData()
{
startShowingLoadingIcon();
presenter.getData(callback);
}
Callback callback(data)
{
stopShowingLoadingIconAndDisplayData(data);
}
I like the second solution because it seems like loading feedback is clearly a user interface decision. I don't want my presenter to have to know about any kind of user interaction. Also, the first solution allows the display some flexibility for the case that the user cancels a request, something else comes up, etc. On the other hand, the first solution is simpler to implement, and doesn't require the display to know about the presenter.
What do you do?
I think it belongs in the view because:
1: The reason you'd take things out of the view is so you can more easily test it. A simple start/ stop showing loading doesn't seem like a lot of logic worth writing tests for.
2: This feature is so specific to the view, that it feels the presenter shouldn't even have to know about it.
3: Since the view is responsible for knowing how to render itself, it makes sense that it should know how to display a loading icon when needed.
Related
I am trying to optimize a webapplication for ipad use. I am now implementing the user interaction and related action / feedback. I have the following idea and was wondering if it is possible to achieve this.
Detect the user-interaction with javascript
Determine what element is touched.
Determine the movement.
Communicate with Wicket
Send the movement to the touched element if it implements a certain interface, i.e., touchable.
The element reacts to the user-interaction by implementing, in the interface, defined methods.
An example of a touchable element could be the following:
public class MyPanel extends Panel implements TouchableElement
#Override
public void react(int x, int y, int movement) {
....
}
}
Could someone tell me if this is possible and/or give me some tips, drawbacks et cetera. Every piece of feedback is helpfull.
Could someone tell me if this is possible and/or give me some tips, drawbacks et cetera.
This would certainly be possible by creating your own AJAX Behavior extending AbstractDefaultAjaxBehavior that "listens" on the user's clicks via javascript and sends any information you calculated within the javascript to the server, where you can react to it in the Behavior's respond() method. A tutorial on how to create your own AJAX Behavior can be found here.
The code would look something like this then:
MyPanel panel = new MyPanel("panel");
panel.add(new MyAjaxBehavior());
However, if all you want is drag and drop you might find existing solutions like Sven Meiers wicket-dnd.
I am developing a Windows Phone7 application in which I have two App bar buttons both when clicked makes Asynchronous calls to Web and Callbacks will be performed upon the Web response.
Now my problem is, if I click on one button and as the Async operation is going on in the background ans meanwhile if I click on another button both callbacks are executing one after the other, which is not good for obvious reasons. Could any one help me on how to handle this???
First I thought to disable other buttons when 1 Async operation is going. But it doesnt give good feel for user. So what will be the best way to handle this problem??
You can use a Flag variable and check its value within the async call complete method. Based on your requirement you can choose to update or not update the view.
I was looking for the same answer.
I have found the solution, If you initialize an object inside a constructor like this, you will get multiple loops when you call a service function:
public partial class MainPage : PhoneApplicationPage
{
MovieServiceClient mov;
public MainPage()
{
mov = new MovieServiceClient(); //Don't do this.
InitializeComponent();
}
}
Avoid that.
Is there a best practice for handling tombstoning and back key properly?
As it is stated in the MSDN docu you should save transient data in the OnNavigatedFrom method. Ok, so the code for saving states when tombstoning is clear.
But now if you press the back key the OnNavigatedFrom method is also called and if you don't add extra checks, you will first save states into the dictionary and shortly after that the page will be destroyed. And so will the PhoneApplicationPage.State dictionary. So the saving code is completely wasted CPU, disk and battery time.
This is what I've done to prevent it:
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
// when navigating back
if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
{
backKeyPressed = true;
}
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
if (backKeyPressed)
{
// Don't save states on back key!
backKeyPressed = false; // set it anyway
return;
}
// Tombstoning
// save objects
this.SaveState("text", someText);
...
}
As a reminder: OnNavigatingFrom will only be called when navigating away/back from the page but not when app gets tombstoned.
Side note: Shown code covers only pages that can only navigate back. Thats why I added backKeypressed to OnNavigatingFrom. You need extra checks if the page can navigate to another page.
Is there a better way to do this for every page you create?
Now do I really have to add the backKeyPressed variable and check on every page I create?
Shouldn't the framework provide something for us developer so we don't have to worry much about this?
What are your thoughts about this?
EDIT:
Updated question the make it clearer.
your approach of checking the direcetion of navigation in OnNavigatingFrom is indeed the recommended practice in order to avoid the unneccessary performance hit of saving state just before the page gets removed from the backstack.
There is one clarification I want to add to your sample code: You should check the 'NavigationMode' property in the 'NavigationCancelEventArgs' to determine whether it's a forward or backward navigation.
Then only save the state in OnNavigatedFrom if it was a forward navigation, as your sample shows. This will help improve your performance when the user navigates backwards.
Everything you ever needed to know about tombstoning is covered in Jeff Prorise's 4-part Real-World Tombstoning in Silverlight for Windows Phone 7 blog post series. You may want to pay particular attention to part 2 where Jeff talks about clearing up state when the application quits.
Right now, I'm working on my first WP7 app and have run into some questions, which I haven't been able to answer despite reading what I could find online. Please consider an app that has a main page, a parameters page and a results page. In the parameters page, the user can enter or update numbers in various textboxes. Hitting the back button takes the user back to the main page, where there is a button called "Calculate". Hitting that button should take the data, perform a calculation with it and take the user to the results page presenting a grid with the results.
In a file called Calculator.cs I have a class called Calculator inside a folder called Models. I also have my MainViewModel.cs, ParametersViewModel.cs, and ResultsViewModel.cs files inside the ViewModels folder and the corresponding MainPage.xaml, along with Parameters.xaml and Results.xaml inside a folder called Views. I'm assuming that all the data will be manipulated within the instance of the Calculator class and then a results set will be returned and directed to Results.xaml. I'm just at a loss as to where to instantiate the Calculator class, pass it data, then retrieve the results. I'm also somewhat puzzled how I will trigger the automatic navigation to the Results page when the calculation is done.
Any help with this would be greatly appreciated.
UPDATE: Passing a complex object to a page while navigating in a WP7 Silverlight application has some more info on the same subject. I can go into App.xaml.cs and add something like this:
public class Foobar
{
public string barfoo = "hah!";
}
public static Foobar myfoob = new Foobar();
Then access it from a ViewModel page, e.g. AboutViewModel.cs, like this:
public AboutViewModel()
{
string goo = App.myfoob.barfoo;
}
But at this point I'm still uncertain what unforseen effects that might have. I'm going to tackle serialization/tombstoning at this point to see what happens with either this approach or by using the same DataContext across pages. Otherwise, one of the posters in the link above mentioned serializing the params and passing them between pages. My concern there would be whether or not there is a character limit as with HTTP GET. Seems there is: URI Limits in Silverlight
There are of course lots of possible designs - and lots of them are correct in different ways!
Here's one I might use:
The Calculate button press should trigger the Navigate to the Results page
On navigate to, the Results page should show some animation (maybe just a progress bar)
On navigate to, the Results page should create a new ResultsViewModel, passing in the MainViewModel as parameters
the constructor (or some init method) of the ResultsViewModel should spark up a thread to do the calculation
when this calculation is complete, then the relevant properties of the ResultsViewModel will get set
at which point the databinding on the Results page will clear the animation and show the results
Other solutions are definitely available - will be interested to read what other people suggest and prefer.
As an aside, one thing to watch out for on your Results page is tombstoning - could be an interesting challenge!
I'm currently putting together a multi-tenancy web app using MVC 3. At least 30 different Web sites will share a common codebase, and while also sharing similar under-the-hood functionality, they are need to look significantly different. As a consequence I'm using the URL to internally separate out clients, and an overridden Razor view engine (at least in terms of finding the view) to automatically select either a customised view for a given action, or the default view.
To help 'compartmentalise' a complex page, any particular view will make use of several partials, usually rendered as self-contained actions, so that generally a custom view or partial view will only have small HTML differences, helping to minimise any code specific to a client's site.
I hope you followed that background!
So one HTML page might be made up of lots of little smatterings of HTML partial views, which could come from specific folders for the client, or a general-purpose version. I'm hoping to make it easier for our designer to make minor changes to a page by easily seeing where in the folder structure the bit of HTML he wants to change are.
My proposal then is that each partial will be 'bracketed' with HTML comments such as:
{ Content of partial }
Obviously I could put these in manually, but that's just asking for trouble, for typos, for copied and then modified client versions not being updated with the correct URL. It should be possible to get this from some context and inject it, I think.
At the same time, I need to be able to not do this for certain Actions. Eg, a partial might be generating text inside a textarea, say, so the comments wouldn't be appropriate there. On the whole I'm happy to put these comments in unless I specify that it's not appropriate.
For me this suggests an ActionFilter on an Action, which I can apply site wide and then turn off for certain Actions. I'd hope that one of the overridable events would let me ascertain this path, but I can't seem to find anywhere it's stored. Furthermore, OnResultExecuting seems to fire before the Partial has been selected, and OnResultExecuted seems to have already written out the contents of the Partial, so I can't insert the starting comment here. I also can't find any reference to the path of the selected partial.
Just for completeness, it's my intention that this attribute would only write these comments when compiled in Debug mode.
So, does anyone know how I might be able to get the path to the selected View without any kind of hack between FindPartialView and the Attribute? Is my Attribute method the best choice or is there an easier way to do this? Perhaps something's built in already!
Many thanks for your help.
Well, I've never forgotten about wanting this, and always hoped I'd solve it one day, and thankfully I have.
I've overridden the default WebViewPage (I use the Razor engine), and in particular ExecutePageHierarchy to inject the comments:
public abstract class PaladinWebViewPage : PaladinWebViewPage<dynamic>
{
}
public abstract class PaladinWebViewPage<TModel> : WebViewPage<TModel>
{
public bool DisplaySourceCodeComments
{
get { return ((bool?) ViewBag.__DisplaySourceCodeComments) ?? false; }
set { ViewBag.__DisplaySourceCodeComments = value; }
}
public override void ExecutePageHierarchy()
{
base.ExecutePageHierarchy();
// Filters can be used to set and clear this value so we can decide when to show this comment
if (!DisplaySourceCodeComments) return;
var sw = Output as StringWriter;
if (sw == null) return;
var sb = sw.GetStringBuilder();
sb.Insert(0, string.Format("<!-- Start of {0} -->", VirtualPath));
sb.AppendFormat("<!-- End of {0} -->", VirtualPath);
}
VirtualPath tells us the exact file used to build the HTML, so we can inject the filename before and after. This isn't doing anything at the moment, since the default is to not show comments (the "?? false" in DisplaySourceCodeComments).
Also to use this view page you need to edit Views/Web.config and change the pageBaseType to this type.
I want to selectively turn these comments on and off so I've created an ActionFilter:
public class DisplaySourceCodeCommentsAttribute : ActionFilterAttribute
{
private readonly bool _displaceSourceCodeComments;
public DisplaySourceCodeCommentsAttribute(bool displaceSourceCodeComments)
{
_displaceSourceCodeComments = displaceSourceCodeComments;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var viewResult = filterContext.Result as ViewResultBase;
if (viewResult == null) return;
viewResult.ViewBag.__DisplaySourceCodeComments = _displaceSourceCodeComments;
}
}
I'm slightly unhappy that I've had to use the ViewBag here and also separately in the view page override, as they aren't tightly linked, but I can't find a way for the filter to directly interact with the view page, so this is something of a necessary fudge. It does have the benefit that displaying source code for a view or partial also automatically displays it for any child partials until you turn it off again, since the ViewBag is passed down the chain.
With this in place, any action can turn on the source code comments with
[DisplaySourceCodeComments(true)]
or, obviously turn it off again with false
The Attribute checks that the context result is a ViewResultBase, which means just Views and Partials, so Json or Content or redirects aren't affected, which is very handy too.
Finally, I make this action filter a global when running in debug mode so that every view, and partial has the source comment included, by adding the following line to global.asax.cs:
[#]if DEBUG
// When in debug mode include HTML comments showing where a view or partial has come from
GlobalFilters.Filters.Add(new DisplaySourceCodeCommentsAttribute(true));
[#]endif
I'm really happy I've finally got it sorted so I hope this is useful for someone else.