问题
I am using IsolatedStorageSettings to store a contact list for a key in my app. But the app only stores the list till the app is active(i.e. like navigating from one page to another). If I exit the app and again relaunch it, the stored key/contact list is not found. How do i permanently save a list for an app, till the app is installed? Here is the code of my viewmodel, I am using:
public class ContactsViewModel : ViewModelBase
{
private static IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;
private List<SavedContact> _SavedContactsList;
public ContactsViewModel()
{
Contacts cons = new Contacts();
cons.SearchAsync(String.Empty, FilterKind.None, null);
cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(OnContactSearchCompleted);
SaveSavedContactsCommand = new RelayCommand(OnSaveSavedContacts);
}
private List<SavedContact> GetSavedContacts()
{
if (appSettings.Contains("SavedContacts"))
{
var savedContacts = (List<SavedContact>)appSettings["SavedContacts"];
return savedContacts;
}
else
{
return new List<SavedContact>();
}
}
public RelayCommand SaveSavedContactsCommand { get; set; }
private void OnSaveSavedContacts()
{
if (!SavedContactsList.Any(x => x.IsSelected == true))
{
MessageBox.Show("Please select some contacts and then click on Save button.");
}
else
{
var selectedSavedContacts = SavedContactsList.Where(x => x.IsSelected == true).ToList();
SavedContacts = selectedSavedContacts;
MessageBox.Show("Emergency contact list added successfully.");
App.RootFrame.GoBack();
}
}
void OnContactSearchCompleted(object sender, ContactsSearchEventArgs e)
{
try
{
SavedContactsList = new List<SavedContact>();
var allContacts = new List<Contact>(e.Results.Where(x => x.PhoneNumbers.Count() > 0).OrderBy(c => c.DisplayName));
// var savedContacts = GetSavedContacts();
var savedContacts = SavedContacts;
foreach (Contact contact in allContacts)
{
SavedContact SavedContact = new SavedContact() { Contact = contact };
if (savedContacts.Any(x => x.Contact.PhoneNumbers.ElementAt(0).PhoneNumber == contact.PhoneNumbers.ElementAt(0).PhoneNumber))
{
SavedContact.IsSelected = true;
}
else
{
SavedContact.IsSelected = false;
}
SavedContactsList.Add(SavedContact);
}
}
catch (System.Exception ex)
{
MessageBox.Show("Error in retrieving contacts : " + ex.Message);
}
}
[DataMember]
public List<SavedContact> SavedContactsList
{
get { return _SavedContactsList; }
set
{
_SavedContactsList = value;
RaisePropertyChanged("SavedContactsList");
}
}
private List<SavedContact> SavedContacts
{
get
{
if (appSettings.Contains("SavedContacts"))
{
var savedContacts = (List<SavedContact>)appSettings["SavedContacts"];
return savedContacts;
}
else
{
return new List<SavedContact>();
}
}
set
{
appSettings["SavedContacts"] = value;
}
}
}
And the class SavedContact is followings:
[DataContract]
public class SavedContact : INotifyPropertyChanged
{
public SavedContact() { }
private bool _isSelected;
private Contact _contact;
[DataMember]
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
if (_isSelected != value)
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
[DataMember]
public Contact Contact
{
get
{
return _contact;
}
set
{
if (_contact != value)
{
_contact = value;
OnPropertyChanged("Contact");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Where the view model is bound to a <toolKit: LongListMultiSelector />
. The functionality is like, I select some contacts from my longlist multiselector and save it in storage to reuse it later. But if I exit the app and restarts it , the savedContacts returns null. While I navigate other pages in my app, the savedContacts is getting printed.
If I save a list first time , on app relaunch GetSavedContacts() returns a new list.
回答1:
The problem isn't related to IsolatedStorageSettings
or your RelayCommand
. Looking in more detail the problem is with serialization and de-serialization of the Contact
object. If you update your implementation to something like the example below, you should be fine.
public class ContactsViewModel : ViewModelBase
{
private static IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;
private List<UserContact> _contactList;
public ContactsViewModel()
{
Contacts cons = new Contacts();
cons.SearchAsync(String.Empty, FilterKind.None, null);
cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(OnContactSearchCompleted);
SaveSavedContactsCommand = new RelayCommand(OnSaveSavedContacts);
}
public RelayCommand SaveSavedContactsCommand { get; private set; }
private void OnSaveSavedContacts()
{
if (!Contacts.Any(x => x.IsSelected == true))
{
MessageBox.Show("Please select some contacts and then click on Save button.");
}
else
{
var selectedSavedContacts = Contacts.Where(x => x.IsSelected == true).Select(x => new SavedContact{ Name = x.Contact.DisplayName, PhoneNumber = x.Contact.PhoneNumbers.ElementAt(0).PhoneNumber}).ToList();
SavedContacts = selectedSavedContacts;
MessageBox.Show("Emergency contact list added successfully.");
App.RootFrame.GoBack();
}
}
void OnContactSearchCompleted(object sender, ContactsSearchEventArgs e)
{
try
{
Contacts = new List<UserContact>();
var allContacts = new List<Contact>(e.Results.Where(x => x.PhoneNumbers.Count() > 0).OrderBy(c => c.DisplayName));
foreach (Contact contact in allContacts)
{
UserContact SavedContact = new UserContact() { Contact = contact };
if (SavedContacts.Any(x => x.PhoneNumber == contact.PhoneNumbers.ElementAt(0).PhoneNumber))
{
SavedContact.IsSelected = true;
}
else
{
SavedContact.IsSelected = false;
}
Contacts.Add(SavedContact);
}
}
catch (System.Exception ex)
{
MessageBox.Show("Error in retrieving contacts : " + ex.Message);
}
}
[DataMember]
public List<UserContact> Contacts
{
get { return _contactList; }
set
{
_contactList = value;
RaisePropertyChanged("Contacts");
}
}
public List<SavedContact> SavedContacts
{
get
{
if (appSettings.Contains("SavedContacts"))
{
var savedContacts = (List<SavedContact>)IsolatedStorageSettings.ApplicationSettings["SavedContacts"];
return savedContacts;
}
else
{
return new List<SavedContact>();
}
}
set
{
if (value != null)
{
IsolatedStorageSettings.ApplicationSettings["SavedContacts"] = value;
IsolatedStorageSettings.ApplicationSettings.Save();
}
}
}
}
public class SavedContact
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
}
[DataContract]
public class UserContact : INotifyPropertyChanged
{
public UserContact() { }
private bool _isSelected;
private Contact _contact;
[DataMember]
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
if (_isSelected != value)
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
[DataMember]
public Contact Contact
{
get
{
return _contact;
}
set
{
if (_contact != value)
{
_contact = value;
OnPropertyChanged("Contact");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
回答2:
Key/Value pairs added to the applications IsolatedStorageSettings are persisted until the application is un-installed or the item is removed from the dictionary. This is true for between application restarts and when the device is powered on and off.
Your SaveList method could be simplified to the example below as it's only necessary to check .Contains
when retrieving a value from the settings dictionary as it will throw an exception if the entry cannot be found.
private void SaveList()
{
appSettings["SavedContacts"] = urls;
}
Alternatively you could use a property to handle all access to IsolatedStorageSettings using something like the example below:
private IList<Contact> Contacts
{
get
{
return appSettings.Contains("SavedContacts") ? (List<Contact>)appSettings["SavedContacts"] : null;
}
set
{
appSettings["SavedContacts"] = value;
}
}
来源:https://stackoverflow.com/questions/19279668/using-isolatedstoragesettings-to-store-information-permanently-for-an-app-in-wp8