Does WP7 save variables on close? - variables

When my app closes will the values i have set still be there when I re open it?
Or is there a way to save them somewhere?

No they won't,
When you jump-out from the application, application will go to a state called TombStoned, it is your responsibility to store and retrieve useful page elements.
In order to do this, you need to store information on the following event on your page:
public override void OnNavigatedFrom(...)
{
State["XXX"] = txtName.Text; // save your data on page state (keep it low in size!)
}
the same way you need to retrieve your data on the following event
public override void OnNavigatedTo(...)
{
txtName.Text = State["XXX"]; // read your data from page state
// also check if state has any entry with this key
}
If you need to store application level data, you need to do it in your App.xaml.cs in the following events:
public override void OnDeactivated(...)
{
// Store in IsolatedStorageSettings
}
public override void OnActivated(...)
{
// Read from IsolatedStorageSettings
}
For more details about Tombstoning read the following article:
http://www.scottlogic.co.uk/blog/colin/2011/05/a-simple-windows-phone-7-mvvm-tombstoning-example/

When you app closes, all data information is lost unless you save it somewhere. For transient data, like page state things (e.g. textboxes, checkbox etc..), you can use PhoneApplicationPage.State. If you need to store data permanently so that it's there the next time the user launches the app, you should store it in Isolated Storage. You can learn more about tombstoning and when you should store states in this MSDN page.
There is also a helper library on CodePlex called Tombstone Helper which will make it easier to store data during tombstoning.

Related

A confusing situation on my way to understand DDD

Thank you in advance for your help and attentation!
My project is dedicated only for learning purposes and I'm totally confused with DDD and have the following situation:
There is the ubiquitous language of my domain where I have users and documents. It says the following:
- A user can create a document. One of the main purpose of my project is to provide users an ability to create different documents. I mean that the documents cannot exist without the users. So,I think that the process of a document creation belongs to my domain.
- A user can send a document for approval. It's one more thing that belongs to the domain. An approval process is one of the most important part of the project. It has its steps that other users must confirm.
- A user can approve a step of approval process.
- A user can reject a step of approval process.
That's enough to understand and answer my question:
Is it normal that a User can contain such methods as: CreateDocument(params), SendDocumentForApproval(docId), ApproveApprovalStepOfDocument(stepId)?
I'm comfused with it because It looks in code a bit strange.
For example for the document creatation process we have something like that:
public async Task<bool> CreateDocumentCommandHandler(CreateDocumentCommand command)
{
//We have our injected repositories
User user = await _userRepository.UserOfId(command.UserId);
Document document = User.CreateDocoment(command.*[Params for the document]);
_documentRepostiory.Add(document);
// It raises event before it makes a commit to the database
// It gets event from an entity. The entity keeps it as readonly collection.
// Here it raises DocumentCreatedEvent. This event contains logic which concerns
// creation some additional entities for the document and log actions.
await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
The approval process:
//The first try out to model this process:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
//We have our injected repositories
User user = await _userRepository.UserOfId(command.UserId);
//Here I have some problems.
//Is it okay that the method returns the document?
//The method that is placed inside the User has this logic:
//public Document SendDocumentForApproval(int docId)
//{
// Document document = this.GetDocument(docId);
//
// //Inside this method ChangedStatusToApproving is created
// document.SetStatusToApproving();
// return document;
//}
Document document = User.SendDocumentForApproval(command.DocId);
_documentRepostiory.Upadate(document);
// It raises event before it makes a commit to the database
// It gets event from an entity. The entity keeps it as readonly collection.
// Here it raises ChangedStatusToApproving. This event contains logic which concerns
// creation some additional entities for the document and log actions.
await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//Is it okay to do something like the command handler above?
//The second one:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
//We have our injected repositories
User user = await _userRepository.UserOfId(command.UserId);
//The same one as we have in the previous method.
//But here I don't want to put the logic about the changing status of the doucnent inside it.
Document document = User.SendDocumentForApproval(command.DocId);
//I see that it breaks the method above (SendDocumentForApproval)
//Now It doesn't mean anything for our domain, does it?
//It is only getter like User.GetDocument or we can even do it
//by using repository - documentRepository.DocumentOfId(docId)
document.SetStatusToApproving();
_documentRepostiory.Upadate(document);
await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
// So, I think the first one is better, isn't it? It follows the ubiquitous language.
//And here is the final question: Why can't I do it like this:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
//Here we don't want to use the userRepository. We don't need at all
//Here as a consequence we also don't need a user entity
//Everything what we need is:
Document document = _documentRepository.DocOfId(command.DocId);
document.ForApproval();
_documentRepostiory.Upadate(document);
await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//I think that the last approach breaks the ubiquitous language and we're about to having an anemic model.
//But here we have only two queries to the database because we don't need a user.
//Which of the approaches is better? Why? How can I do it more correctly if I want to apply DDD?
I want to explain my thoughts in more details.
Let's have a look at the user. They manage documents. A Document cannot exist without the user. Does it mean that the User is an aggregate root through we need to create, update, delete its aggregates.
And the document is also an aggregate root due to it contains an apporval process. The ApprovalProcess cannot exist without the document.
Does it mean that I need to do something like this:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
Document document = _documentRepository.DocumentOfId(command.DocId);
document.SendForApproval();
_documentRepository.SaveChangesAsync();//Raise a domain event - SentDocumentForApprovalEvent
}
// Here we have a handler for the event SentDocumentForApprovalEvent
public async Task SentDocumentForApprovalEventHandler(SentDocumentForApprovalEvent sentDocumentForApprovalEvent)
{
//Now I want to create an approval process for the document
//Can I do the next thing:
ApprovalProcess process = new ApprovalProcess(sentDocumentForApprovalEvent.DocId);
_approvalProcessRepository.Add(process);
_approvalProcessRepository.SaveEntitiesAsync();//Raise a domain event - InitiatedApprovalProcessEvent
//Or Should I create the approval process through Document?
//Looks terrible due to we need to call the repostiory amd
ApprovalProcess process = Document.InitiateApprovalProcess(sentDocumentForApprovalEvent.DocID);//Static method
_approvalProcessRepository.Add(process);
_approvalProcessRepository.SaveEntitiesAsync();
//log
}
// Here we have a handler for the event InitiatedApprovalProcessEvent
public async Task InitiatedApprovalProcesEventHandler(SentDocumentForApprovalEvent sentDocumentForApprovalEvent)
{
//The same question as we have with handler above.
//Should I create steps trough the approval process or just with the help of constructor of the step?
//log
}
Thank you so much and sorry for my terrible English!
Best regards
Is it normal that a User can contain such methods as: CreateDocument(params), SendDocumentForApproval(docId), ApproveApprovalStepOfDocument(stepId)?
In most domain models, the method belongs with the entity that manages the state that is going to change.
Document document = User.SendDocumentForApproval(command.DocId);
_documentRepository.Update(document);
The fact that your sample is updating the document repository here is a big hint that it is the document that is changing, and therefore we would normally expect to see SendDocumentForApproval as a method on the document.
document.SendDocumentForApproval(command.UserId)
_documentRepository.Update(document);
(Yes, the code doesn't read like written or spoken English.)
When creating a new document... creation patterns are weird. Udi Dahan suggests that there should always be some entity in your domain model that is responsible for creating the other entities, but I'm not convinced that the result is actually easier to work with in the long term.
How can we model the approval business process
General answer: business processes are protocols, which is to say that you can normally model them as a state machine. Here's the state we are in right now, here is some new information from the outside world, compute the consequences.
(Often, the data model for a process will just look like a history of events; the domain model's job is to then take the new information and compute the right events to store in the history. You don't have to do it that way, but there are interesting possibilities available when you can).
You are headed in a right direction, User and Document both are aggregates as they are created in separate transactions. When it comes to who references whom, IDDD principle of scalability says that aggregates should refer aggregates only via their IDs.
I think sticking to the ubiquitious, language your code should look something like this
class User {
private UserId id;
private String name;
User(String name) {
this.id = new UserId();
this.name = name;
}
Document createDocument(String name) {
Document document = new Document(name);
document.createdBy(this);
return document;
}
Document approve(Document document) {
document.approved();
return document;
}
}
class Document {
private DocumentId id;
private String name;
private UserId userId;
private Boolean isApproved;
Document(String name) {
this.id = new DocumentId();
this.name = name;
}
void createdBy(UserId userId) {
this.userId = userId;
}
void approved() {
this.isApproved = true;
}
}
// User creation
User user = new User("Someone");
userRepository.save(user);
//Document creation
User user = userRepository.find(new UserId("some-id"))
Document document = user.createDocument("important-document")
documentRepository.save(document)
// Approval
User user = userRepository.find(new UserId("some-id"))
Document document = documentRepository.find(new DocumentId("some-id"))
document = user.approve(Document)
I would highly recommend reading Vaughn Vernon's three part aggregate design paper series better aggregete design

How to click back button programatically in IWizardPage in Eclipse

I'm writing an Eclipse plugin, I want to create a wizard for my new project type. I created pages by classes extends org.eclipse.jface.wizard.WizardPage. My requirement is, based on some condition in one page, I need to go back to previous page without pressing back button on page(programmatically).
Is it possible?
Thanks a million in advance!
I don't think this is a good idea. The user will be confused by doing this. I would disable the finish and the next button and give an error, telling the user that he has to go back to the first page.
If you want to reuse some UI from the first page, define the UI as a new class and reuse it.
I implemented something similar using the WizardDialog:showPage() method:
MyWizard.java
public void createPageControls(Composite pageContainer) {
// TODO Auto-generated method stub
super.createPageControls(pageContainer);
wizardDialog = (WizardDialog) getContainer();
}
public void skipProcessPage() {
wizardDialog.showPage(workPage == arisDbPage ? focusPage : arisDbPage);
}
public void setWorkPage(IWizardPage workPage) {
this.workPage = workPage;
}
here the processPage does the lengthy db lookup!
HTH thomas

How to create new instance of a view/viewmodel when navigation occurs with Prism

I am trying to control when a new view is created and when an existing view is shown.
This is a very similar scenario as outlined in the "Navigating to Existing Views" section in the Prism documentation, but I can't get it to work fully:
http://msdn.microsoft.com/en-us/library/gg430861(v=pandp.40).aspx
I am finding I can create the view/view model to begin with ok, but I am then unable to create a new instance of it. I.e. I want more than one instance to exist at once.
Here's an example of the view model:
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class DataEntryPageViewModel : INavigationAware, IRegionMemberLifetime
{
private Guid id;
[ImportingConstructor]
public DataEntryPageViewModel()
{
id = Guid.NewGuid();
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
// In actual fact there would be more logic here to determine
// whether this should be shown to the user
return false;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
public bool KeepAlive
{
// For the purposes of this example we don't want the view or the viewModel
// to be disposed of.
get { return true; }
}
}
I am navigating to this as follows:
m_RegionManager.RequestNavigate(
"MainRegion",
new Uri("/DataEntryPageView", UriKind.Relative));
So the first time I call the above the view is shown.
The next time I call RequestNavigate the IsNavigationTarget is hit and it returns false. What I then want it to do is to create a new instance but that doesn't happen. I know it's not happening because the constructor does not get hit and the UI does not update to show the new instance of the view.
Any ideas how I can make it create a new instance?
Many thanks,
Paul
Edit
I have noticed that the second time I call RequestNavigate (to request another instance of the same view) the callback reports an error "View already exists in region." It therefore seems that I can have multiple instances of different views in a region, but not multiple instances of the same view. My understand of this isn't great though so I could be wrong.
Why are you not creating the view when you want a new one to be created? It looks to me like you are using MEF.
Use the container to resolve a new instance of your view
Add the new instance of the view to the MainRegion
Then call Navigate and handle the appropriate logic in IsNavigationTarget
You should use the [Export] attribute in your view with a contract name: [Export("DataEntryPageView")].
I have now been able to get this to work, it was because I didn't have
[PartCreationPolicy(CreationPolicy.NonShared)]
on the class declaration of the view. I had it on the ViewModel.
So this is now resulting in the behaviour I expected.
Thanks though to Zabavsky and Alan for your suggestions.

Relation many-to-one retrieved from custom cache

It's more like theoretical question.
I have one table to hold dictionary items, and the next one for hold Users data.
User table contains a lot reference collumns of type many to one indicated on dictionary item table. It's looks like:
public class User
{
public int Id;
public Dictionary Status;
public Dictionary Type;
public Dictionary OrganizationUnit;
......
}
I want retrieve all dictionary on startup of aplication, and then when i retrieved user and invoke reference property to dictionary the dictionary object should be taken from cache.
I know i can use a 2nd level cache in this scenario, but i'm interested about other solution. Is there any?
It's posible to make my custom type and said that: use my custom cache to retrieved value of dictionary??
Across multiple session the second level cache is the best answer, the only other solutions to populate objects from a cache without using second level cache i can think of would be to use an onLoad interceptor (and simply leave your dictionaries unmapped) or do it manually somewhere in your application.
But why don't you want to use the seocondlevel cache? If your views on caching is very different from the storages there are providers for in hibernate it is possible for you to implement your own provider?
Why not store it in the session? Just pull the record set one time and push it into session and retrieve it each time you want it. I do something similar for other stuff and I believe my method should work for you. In my code I have a session manager that I call directly from any piece of code needs the session values. I choose this method since I can query the results and I can manipulate the storage and retrieval methods. When relying on NHibernate to do the Caching for me, I don't have the granularity of control to cause specific record sets to only be available to specific sessions. I also find that NHibernate is not as efficient as using the session directly. When profiling the CPU and memory usage I find that this method is faster and uses a little less memory. If you want to do it on a site level instead of session, look into HttpContext.Current.Cache.
The following example works perfectly for storing and retrieving record sets:
// Set the session
SessionManager.User = (Some code to pull the user record with relationships. Set the fetch mode to eager for each relationship else you will just have broken references.)
// Get the session
User myUser = SessionManager.User;
public static class SessionManager
{
public static User User
{
get { return GetSession("MySessionUser") as User; }
set { SetSession("MySessionUser", value); }
}
private static object GetSession(string key)
{
// Fix Null reference error
if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.Session == null)
{
return null;
}
else
{
return System.Web.HttpContext.Current.Session[key];
}
}
private static void SetSession(string key, object valueIn)
{
// Fix null reference error
if (System.Web.HttpContext.Current.Session[key] == null)
{
System.Web.HttpContext.Current.Session.Add(key, valueIn);
}
else
{
System.Web.HttpContext.Current.Session[key] = valueIn;
}
}
}

RavenDB Catch 22 - Optimistic Concurrency AND Seeing Changes from Other Clients

With RavenDB, creating an IDocumentSession upon app start-up (and never closing it until the app is closed), allows me to use optimistic concurrency by doing this:
public class GenericData : DataAccessLayerBase, IGenericData
{
public void Save<T>(T objectToSave)
{
Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
Session.Store(objectToSave, eTag);
Session.SaveChanges();
}
}
If another user has changed that object, then the save will correctly fail.
But what I can't do, when using one session for the lifetime of an app, is seeing changes, made by other instances of the app (say, Joe, five cubicles away), to documents. When I do this, I don't see Joe's changes:
public class CustomVariableGroupData : DataAccessLayerBase, ICustomVariableGroupData
{
public IEnumerable<CustomVariableGroup> GetAll()
{
return Session.Query<CustomVariableGroup>();
}
}
Note: I've also tried this, but it didn't display Joe's changes either:
return Session.Query<CustomVariableGroup>().Customize(x => x.WaitForNonStaleResults());
Now, if I go the other way, and create an IDocumentSession within every method that accesses the database, then I have the opposite problem. Because I have a new session, I can see Joe's changes. Buuuuuuut... then I lose optimistic concurrency. When I create a new session before saving, this line produces an empty GUID, and therefore fails:
Guid eTag = (Guid)Session.Advanced.GetEtagFor(objectToSave);
What am I missing? If a Session shouldn't be created within each method, nor at the app level, then what is the correct scope? How can I get the benefits of optimistic concurrency and the ability to see others' changes when doing a Session.Query()?
You won't see the changes, because you use the same session. See my others replies for more details
Disclaimer: I know this can't be the long-term approach, and therefore won't be an accepted answer here. However, I simply need to get something working now, and I can refactor later. I also know some folks will be disgusted with this approach, lol, but so be it. It seems to be working. I get new data with every query (new session), and I get optimistic concurrency working as well.
The bottom line is that I went back to one session per data access method. And whenever a data access method does some type of get/load/query, I store the eTags in a static dictionary:
public IEnumerable<CustomVariableGroup> GetAll()
{
using (IDocumentSession session = Database.OpenSession())
{
IEnumerable<CustomVariableGroup> groups = session.Query<CustomVariableGroup>();
CacheEtags(groups, session);
return groups;
}
}
Then, when I'm saving data, I grab the eTag from the cache. This causes a concurrency exception if another instance has modified the data, which is what I want.
public void Save(EntityBase objectToSave)
{
if (objectToSave == null) { throw new ArgumentNullException("objectToSave"); }
Guid eTag = Guid.Empty;
if (objectToSave.Id != null)
{
eTag = RetrieveEtagFromCache(objectToSave);
}
using (IDocumentSession session = Database.OpenSession())
{
session.Advanced.UseOptimisticConcurrency = true;
session.Store(objectToSave, eTag);
session.SaveChanges();
CacheEtag(objectToSave, session); // We have a new eTag after saving.
}
}
I absolutely want to do this the right way in the long run, but I don't know what that way is yet.
Edit: I'm going to make this the accepted answer until I find a better way.
Bob, why don't you just open up a new Session every time you want to refresh your data?
It has many trade-offs to open new sessions for every request, and your solution to optimistic concurrency (managing tags within your own singleton dictionary) shows that it was never intended to be used that way.
You said you have a WPF application. Alright, open a new Session on startup. Load and query whatever you want but don't close the Session until you want to refresh your data (e.g. a list of order, customers, i don't know...). Then, when you want to refresh it (after a user clicks on a button, a timer event is fired or whatever) dispose the session and open a new one. Does that work for you?