private void btn_friends_pressed(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/Friends.xaml", UriKind.Relative));
}
When I press the button I go to the Friends page, which loads many friends from isolated storage.Than I press "back" button and go to the Menu page, when I press again the button, I have "Operation not permitted on IsolatedStorageFileStream." message.
How I can not reload page and keep it in RAM.
Something like:
if (Friends.Page.IsRunning==true)
NavigationService.Navigate("/Friends.xaml");
else
NavigationService.Navigate(new Uri("/Friends.xaml", UriKind.Relative));
Whenever you navigate to a page, it is reloaded automatically. The pages themselves are not kept in memory once you've navigated away from them. If you want to store it memory, and not read it from Isolated Storage each time, then you can simply create a static class that contains a static List that stores your friends. Once you've loaded your friends, depending on their type, you can add it to the list. Whenever you need to access them, simply call it from the static List. For example, in your solution, create a new class:
using ... //your using directives
namespace MyApp //Your project Namespace
{
public static class FriendsStorage //rename `FriendsStorage` to whatever you want
{
public static List<Friends> ListOfFriends = new List<Friends>(); //Your list
}
}
To set it, you can load the information from IsolatedStorage and add it to the list:
foreach(Friend f in Friends)
FriendsStorage.ListOfFriends.Add(f);
Whenever you need to query the Friends list you can call it like this:
var friendList = FriendsStorage.ListOfFriends;
Even if you use the above method, you should try and fix the error you're getting. Can you post your Isolated Storage code?
If you want to get rid of the error message, you should use your stream in a using() block,
using (var stream = new IsolatedStorageFileStream(...))
{
// load your data here
}
Regarding saving page, it's generally not a good idea because your memory can exponentialy grow and your application will be very unresponsive.
Although you can always use your App.xaml.cs as a global instance of your application to cache some of your data sources:
List<Friend> _Friends;
List<Friend> _Friends
{
get
{
if(_Friends == null) _Friends = GetFriends();
return _Friends;
}
}
but if you did this be very careful not to store loads of data.
Related
my project
I was wondering how to save the User input in a ListView and prevent it from disappearing when I go to another Form
if (string.IsNullOrEmpty(txtName.Text) || string.IsNullOrEmpty(txtReview.Text))
return;
ListViewItem item = new ListViewItem(txtName.Text);
item.SubItems.Add(txtReview.Text);
listView1.Items.Add(item);
txtName.Clear();
txtReview.Clear();
As far I got your concern! You have a form in which you are adding a reviews. You are closing it soon after adding review. But you want all previous reviews when you visit that form again.
you cannot use database (it certainly would have been easiest way to do though), but you are allowed to use file system (you said text files, i'm assuming serialization too)
But reading and writing files on every now and then is costly process, I would recommend you keep data in memory cache (insert new reviews, update and delete them if there may such option). While closing an application, you store last updated copy into file and while starting software you read that file to get last updated copy of data.
(this way of storing data on closing software can cause data loss when software crash or stopped abnormally. but as it is class project, i would not worry much about that. however you can always use low priority thread to store data periodically)
For this approach, I would recommend to implement MVVM architecture
At least you should create a class which store all the data statically
(why static? it is an interesting question and i m leaving it on you to find out the answer)
Example code For Model:
public class Model
{
public static Dictionary<string, Review> ReviewData;
//this method should be called at application startup.
public static void SetModel()
{
//Desrialize lastly saved file, I'm just initializing it with new
ReviewData = new Dictionary<string, Review>();
}
public static void AddReview(string movie, string reviewerName, string review)
{
if (!ReviewData.ContainsKey(movie + "-" + reviewerName))
{
ReviewData.Add(movie + "-" + reviewerName, new Review(reviewerName, reviewerName));
}
}
}
public class Review
{
public string reviewerName;
public string review;
public Review(string reviewerName, string review)
{
this.reviewerName = reviewerName;
this.review = review;
}
}
Example Code for Add review form:
private void btnPost_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtName.Text) || string.IsNullOrEmpty(txtReview.Text))
return;
//First we should set Model data
Model.AddReview("moive1", txtName.Text, txtReview.Text);
LoadListView();
}
private void AddReviewForm_Load(object sender, EventArgs e)
{
LoadListView();
}
private void LoadListView()
{
listView1.Clear();
foreach (string reviewKey in Model.ReviewData.Keys)
{
Review review = Model.ReviewData[reviewKey];
ListViewItem item = new ListViewItem(review.reviewerName);
item.SubItems.Add(review.review);
listView1.Items.Add(item);
}
}
And last thing, while closing entire application, store lastly updated copy of Model.ReviewData (Serialize it).
I'm using a List<> as a container for some data returned from database, like this:
List<BookInfo> result {get;set;}
protected void SearchButton_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
result = (new BookInfo()).Search(TextBox1.Text);
ListView1.DataSource = result;
ListView1.DataBind();
}
}
Everything works ok. But when I'm trying to sort this List in other event like this one, it's empty.
protected void ListView1_Sorting(object sender, ListViewSortEventArgs e)
{
IComparer<BookInfo> comparer = new BookInfoOrdering();
if (result != null)
{
result.Sort(comparer);
}
ListView1.DataSource = result;
ListView1.DataBind();
}
I'd just like to know why is it happening. One solution is to call the search method and get the data again but isn't it unnecessary?
You were trapped by the same trap that many people are trapped by many times - it's the page lifecycle. ASP.NET fools you by pretending that you had one environment including server and browser, but that's not the case. HTTP is state-less. If you need to persist state between two requests, you have several options:
Serialize the state into the so-called ViewState such as to send it to the browser and post it back to the server
Save it in a database
Save it in the session
Introduce caching for the data that need to be retrieved, that is, sequential calls to BookInfo.Search with equal parameter values don't issue a new database request (or whatever else is required to get the data)
This would work in a desktop application, but not a asp.net website. Server side data retrieved from one postbacks is not stored for the next postback.
There are several methods for storing data between postbacks. For example using the Session State of the website:
// storing
HttpContext.Current.Session["list"] = result;
// retrieving
List<BookInfo> temp = (List<BookInfo>)HttpContext.Current.Session["list"];
you should also be able to retrieve the list from the ListView where it was bound.
IComparer<BookInfo> comparer = new BookInfoOrdering();
List<BookInfo> temp = (List<BookInfo>)ListView1.DataSource;
temp.Sort(comparer);
ListView1.DataSource = temp;
ListView1.DataBind();
I am currently working on Windows Store App in c#.
Now,
I am having a list box 'Listbox1' which gets its items on a button click event from a text box 'tasks', and have selected Items delete property on other button click event.
private void add_Click(object sender, RoutedEventArgs e)
{
string t;
t = tasks.Text;
if (t != "")
{
Listbox1.Items.Add(t);
}
else
{
var a = new MessageDialog("Please Enter the Task First");
a.Commands.Add(new UICommand("Ok"));
a.ShowAsync();
}
tasks.Text = "";
}
private void del_Click(object sender, RoutedEventArgs e)
{
for (int p = 0; p < Listbox1.SelectedItems.Count; p++)
{
Listbox1.Items.Remove(Listbox1.SelectedItems[p].ToString());
p--;
}
}
Now I want to save this list into local application storage, after user complete the changes (on a button click event perhaps).
And also to send all Listbox Items to another page(s).
I am not much a coder, I design things.
Please guide me by sample or reference.
Thank you in advance :)
If you have already stored the data to local storage, you could just read it in the OnNavigatedTo override of the other page. Otherwise, use the navigation parameter: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/8cb42356-82bc-4d77-9bbc-ae186990cfd5/passing-parameters-during-navigation-in-windows-8
Edit: I am not sure whether you also need some information about local storage. This is easy: Windows.Storage.ApplicationData.Current.LocalSettings has a property called Values, which is a Dictionary you can write your settings to. Have a look at http://msdn.microsoft.com/en-us/library/windows/apps/hh700361.aspx
Edit: Try something like this code to store your list.
// Try to get the old stuff from local storage.
object oldData = null;
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
bool isFound = settings.Values.TryGetValue("List", out oldData);
// Save a list to local storage. (You cannot store the list directly, because it is not
// serialisable, so we use the detours via an array.)
List<string> newData = new List<string>(new string[] { "test", "blah", "blubb" });
settings.Values["List"] = newData.ToArray();
// Test whether the saved list contains the expected data.
Debug.Assert(!isFound || Enumerable.SequenceEqual((string[]) oldData, newData));
Note, this is only demo code for testing - it does not make real sense...
Edit: One advice: Do not persist the list in your click handlers as this will become extremely slow as the list grows. I would load and save the list in the Navigation handlers, i.e. add something like
protected override void OnNavigatedTo(NavigationEventArgs e) {
base.OnNavigatedTo(e);
if (this.ListBox1.ItemsSource == null) {
object list;
if (ApplicationData.Current.LocalSettings.Values.TryGetValue("List", out list)) {
this.ListBox1.ItemsSource = new List<string>((string[]) list);
} else {
this.ListBox1.ItemsSource = new List<string>();
}
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e) {
if (this.ListBox1.ItemsSource != null) {
ApplicationData.Current.LocalSettings.Values["List"] = this.ListBox1.ItemsSource.ToArray();
}
base.OnNavigatedFrom(e);
}
Here is very nice simple example on SQLite DataBase Use in winRT app Development. Look at it and you will know how you can store your Data on the Local Machine. I learned Basic code from this example.
http://blogs.msdn.com/b/robertgreen/archive/2012/11/13/using-sqlite-in-windows-store-apps.aspx
Now, for ease of navigation let me suggest you a flow for this portion of your app.
take one ObservableCollection<> of string and store values of
that textBox into this ObservationCollection with onClick() and then
refer that ObservableCollection<String> to the ItemsList of the
listBox.
now at the time you need to send your Data to the next page, make one parameterised constructor of next page and pass that ObservableCollection<String> as it's parameter.
Now you can access those Data in your constructor and can use as however you want.
Hope this will help..
I have an AppBar with a button that launches a popup that contains a list that the user selects and upon one being selected it refreshes the page, but before it refreshes for a certain page I need it to execute a task. The code works great on my other pages. I just need it to execute
await home.DatabaseTest();
before it refreshes the page and I only want it to execute if the current page is Dashboard
private async void customerNamePopUp_Tapped_1(object sender, TappedRoutedEventArgs e)
{
//Gets the selected Customer Name and stores it in the Database.
barCustomerName = db.selectCustomerNumberByCustomerName(customerNamePopUp.SelectedItem);
rh.appDataHandler(customerNamePopUp.SelectedIndex, barCustomerName);
if ("WHAT DO I PUT HERE TO TEST IF PAGE EQUALS DASHBOARD")
{
await home.DatabaseTest();
}
if (this.Frame != null)
{
//Refreshes Current Page
Frame1.Navigate(Frame1.Content.GetType(), RootPage);
}
}
See note in loop before the await task to know what I am asking for.
Thank you
Create a public enum where each item correlates to each page.
On the App page create a static property of the enum created which will signify the current page.
On each page's OnNavigatedTo method set the app static property to that page's enum.
Wherever needed check that variable for the current page.
I figured it out.
if (Frame1.Content.GetType() == typeof(Dashboard))
{
await home.DatabaseTest();
}
There is a MenuItem click event MainMenu_Define_Material which opens a window called Material. I get info from a textbox called txt_density and I save that info in density and return to main window via OK-button having click event Material_btn_OK_Click.
My question is, how I can avoid passing the last session values every time I open the window Material?
I want, once density is set, every time I open Material window I want to see the values of previous session.
private void MainMenu_Define_Material(object sender, RoutedEventArgs e)
{
newWin_material = new Material();
newWin_material.btn_OK.Click += new RoutedEventHandler(Material_btn_OK_Click);
if (density != -1)
{
newWin_material.txt_density.Text = density.ToString();
}
newWin_material.ShowDialog();
}
private void Material_btn_OK_Click(object sender, RoutedEventArgs e)
{
density = System.Convert.ToSingle(newWin_material.txt_density.Text);
newWin_material.Close();
}
Not very clear where that density comes from, but you can insert that field in uour data class what you can hold on data layer or may be like ObjectDataProvider for modelview.
There are a lor of different solutioms our there. The basic idea is:
Define common, shared data storage and keep there alll values you want to share between different windows.
Define a data class. I used here a static class with a static member Desnity.
public static class DataClass
{
public static double Desnsity;
}
After in any window you're able to access that field (read/write), like
DataClass.Density
Hope this is clear.
There is no concept of Session in WPF. You can try creating a static variable to do this or a app config value or pass a parameter via the constructor.
If you are going to new it ( e.g. new Material(); ) then it is going to start with zero information. That is what new does. What is wrong with passing the value in the ctor?
Try
MainWindow
{
private newWin_material = new Material(); // just new it ONCE
// this may need to be in MainWindow ctor.
newWin_material.btn_OK.Click += new RoutedEventHandler(Material_btn_OK_Click);