I've used a button with this method to deserialize a ObservableCollection but after i can't no more add a object to my list.
private async void RecoveryList_Click(object sender, RoutedEventArgs e)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("List.xml");
DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<ProductClass>));
using (Stream stream = await file.OpenStreamForReadAsync())
{
ObservableCollection<ProductClass> Products = serializer.ReadObject(stream) as ObservableCollection<ProductClass>;
ListView1.ItemsSource = Products;
}
}
And to serialize
private async void ButtonSave_Click(object sender, RoutedEventArgs e)
{
DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<ProductClass>));
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("List.xml", CreationCollisionOption.ReplaceExisting);
using (Stream stream = await file.OpenStreamForWriteAsync())
{
serializer.WriteObject(stream, Products);
ListView1.ItemsSource = Products;
}
}
To add product I've used this
private async void ButtonAdd_Click(object sender, RoutedEventArgs e)
{
Products.Add(new ProductClass{ Prodotti = TexBoxInputProducts.Text });
}
My ObservableCollection is
public ObservableCollection<ProductClass> Products;
My class is
namespace AppSpesaPhone.Models
{
public class ProductClass
{
public string Prodotti { get; set; }
}
}
How can i add some "Product" to my list?
You have a public ObservableCollection<ProductClass> field named Products in your class, but in your RecoveryList_Click method, you use a new ObservableCollection also named Products to retrieve the deserialized list and set it as ListView's ItemsSource. Although they are the same name, but they are not the same object. So you can't add new item to the ListView.
To fix this issue, you can remove the declaration of new Products in RecoveryList_Click method like following and make sure in all methods, you are operating the same object.
private async void RecoveryList_Click(object sender, RoutedEventArgs e)
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync("List.xml");
DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<ProductClass>));
using (Stream stream = await file.OpenStreamForReadAsync())
{
Products = serializer.ReadObject(stream) as ObservableCollection<ProductClass>;
ListView1.ItemsSource = Products;
}
}
Related
I use the following code to connect to firebase and try to read data. The connection is successful but I am unable to read the data. It gives System.NullReferenceException:'Object reference not set to an instance of an object.
namespace GPSTrack
{
public partial class Form1 : Form
{
IFirebaseConfig config = new FirebaseConfig
{
AuthSecret = "4xxxxxxxxxxxxxxxxEzs",
BasePath= "nodxxxxxx.firebaseio.com"
};
IFirebaseClient client;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
client = new FireSharp.FirebaseClient(config);
if(client!=null)
{
MessageBox.Show("Connection success");
}
}
private async void button1_Click(object sender, EventArgs e)
{
FirebaseResponse response = await client.GetTaskAsync("test");
FBclass obj = response.ResultAs<FBclass>();
MessageBox.Show(response.ToString());
}
}
}
The problem might be in the response creation, because you've only placed a parent node, called "test". If that's the only dataset/node in your firebase instance then it might not have returned an exception. If there is a single child node under the "test" parent node, then I would like to suggest hard coding that node in the get call:
FirebaseResponse response = await client.GetTaskAsync("test/childnode");
FBclass obj = response.ResultAs<FBclass>();
Or you can create a call to a textbox asking for a specific ID:
FirebaseResponse response = await client.GetTaskAsync($"test/{ textBox.Text }");
FBclass obj = response.ResultAs<FBclass>();
So far I've followed the textbook route of adding adding data to an XML file; first, I created a class:
[Serializable]
public class Note
{
public string Notes { get; set; }
}
And then done this:
private void addButton_Click(object sender, RoutedEventArgs e)
{
string stringToAdd = textBox.Text;
Notes.Add(stringToAdd);
using (StringWriter myStringWirter = new StringWriter())
{
XmlSerializer myXML = new XmlSerializer(typeof(Note));
Note myNote = new Note();
myNote.Notes = stringToAdd;
myXML.Serialize(myStringWirter, myNote);
using (StreamWriter myStreamWriter = new StreamWriter("Notes.xml"))
{
myStreamWriter.Write(myStringWirter);
}
}
But Notes.xml doesn't get updated. Why?
Edit. Now it works. Just by using List instead of Note.
I create a test app with a local database in Windows phone 8 but I get error and my project can't create my sqlite database
Can you help me ?
Runtime error is this :
An exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.ni.dll but was not handled in user code
Additional information: Exception has been thrown by the target of an invocation.
In this line : val = m.GetValue( obj , null ) ;
Person class :
namespace PhoneApp4
{
public class person
{
[SQLite.AutoIncrement , SQLite.PrimaryKey]
public int ID { get; set; }
public string FullName { get; set; }
}
}
mainpage.xaml.cs:
namespace PhoneApp4
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private async void BTO_save_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite"), true);
person person = new person
{
FullName = TB_save.Text
};
await conn.InsertAsync(person);
}
private async void BTO_search_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "people.db"), true);
var query = conn.Table<person>().Where(x => x.ID == Convert.ToInt32(TB_search.Text));
var result = await query.ToListAsync();
foreach (var item in result)
{
LB_search.Items.Add(item.ID.ToString() + " " + item.FullName.ToString());
}
}
app.xaml.cs:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite");
using (var db = new SQLiteConnection(dbPath))
{
db.CreateTable<person>();
}
}
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite");
if (FileExists("dbsqlite.sqlite").Result)
{
using (var db = new SQLiteConnection(dbPath))
{
db.CreateTable<person>();
}
}
}
// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
string dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "dbsqlite.sqlite");
if (!FileExists("dbsqlite.sqlite").Result)
{
using (var db = new SQLiteConnection(dbPath))
{
db.CreateTable<person>();
}
}
}
See this sample
http://code.msdn.microsoft.com/SQLite-for-Windows-Phone-8-8ff3beaf
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
try
{
await ApplicationData.Current.LocalFolder.GetFileAsync("UniversityDB.db");
Connection = new SQLiteAsyncConnection("UniversityDB.db");
}
catch (FileNotFoundException)
{
DataService.CreateDbAsync();
}
}
and
public static async void CreateDbAsync()
{
App.Connection = new SQLiteAsyncConnection("UniversityDB.db");
var universityTask = App.Connection.CreateTableAsync<University>();
var studentTask = App.Connection.CreateTableAsync<Student>();
await Task.WhenAll(new Task[] { universityTask, studentTask });
}
I open a new MessagesWindow which has this code:
namespace Newsletter.UI
{
public partial class MessagesWindow : Window
{
MessageService msgService;
public MessagesWindow()
{
InitializeComponent();
msgService = new MessageService();
}
private void CreateButtonClick(object sender, RoutedEventArgs e)
{
var createMessageWindow = new CreateMessageWindow { Owner = this };
createMessageWindow.ShowDialog();
gridMessages.ItemsSource = from msg in msgService.GetAllMessages()
select msg;
}
private void messagesWindow_Loaded(object sender, RoutedEventArgs e)
{
gridMessages.ItemsSource = from msg in msgService.GetAllMessages()
select msg;
}
private void EditButtonClick(object sender, RoutedEventArgs e)
{
if (gridMessages.SelectedItem == null)
MessageBox.Show("You have to choose the message first.");
else
{
var selectedMessage = (Message)gridMessages.SelectedItem;
var editMessageWindow = new EditMessageWindow(selectedMessage);
editMessageWindow.Owner = this;
editMessageWindow.ShowDialog();
}
gridMessages.ItemsSource = from msg in msgService.GetAllMessages()
select msg;
}
}
}
I open a new window with EditButtonClick where I want to edit my Message. The code of the EditMessageWindow:
namespace Newsletter.UI
{
public partial class EditMessageWindow : Window
{
private Message editMessage;
private MessageService messageService;
public EditMessageWindow(Message message)
{
InitializeComponent();
editMessage = message;
messageService = new MessageService();
}
private void CreateMessageWindowLoaded(object sender, RoutedEventArgs e)
{
subject.Text = editMessage.Subject;
messageContent.AppendText(editMessage.Content);
senderComboBox.ItemsSource = messageService.GetAllSenders();
mailingListComboBox.ItemsSource = messageService.GetAllMailingLists();
}
private void SaveClick(object sender, RoutedEventArgs e)
{
editMessage.Date = DateTime.Now;
editMessage.Content = messageContent.Text;
editMessage.MailingList.Add(messageService.GetAllMailingLists()[mailingListComboBox.SelectedIndex]); //ERROR
editMessage.Sender = messageService.GetAllSenders()[senderComboBox.SelectedIndex];
editMessage.Subject = subject.Text;
editMessage.HasAttachments = false;
messageService.EditMessage(editMessage);
Close();
}
}
}
I get an error on SaveClick:
The relationship between the two objects cannot be defined because
they are attached to different ObjectContext objects.
Finally, MessageService code:
namespace Newsletter.Services
{
public class MessageService
{
private NewsletterEntities _context;
public MessageService()
{
_context = new NewsletterEntities();
}
public void AddMessage(Message newMessage)
{
_context.Messages.AddObject(newMessage);
_context.SaveChanges();
}
public void EditMessage(Message editMessage)
{
var messageToChange = (from m in _context.Messages where editMessage.MessageID == m.MessageID select m).FirstOrDefault();
if (messageToChange != null)
{
messageToChange = editMessage;
_context.SaveChanges();
}
}
public List<Message> GetAllMessages()
{
return (from m in _context.Messages select m).ToList();
}
public List<MailingList> GetAllMailingLists()
{
var query = from m in _context.MailingLists select m;
return query.ToList();
}
public List<Sender> GetAllSenders()
{
var query = from m in _context.Senders select m;
return query.ToList();
}
public void DeleteMessage(Message message)
{
List<MailingList> mailingLists = new List<MailingList>();
foreach(MailingList ml in message.MailingList.ToList())
{
ml.Message.Remove(message);
}
_context.Messages.DeleteObject(message);
_context.SaveChanges();
}
}
}
I'm getting consfused with all those layers and contexts. I know I should probably somehow detach the message, do something with it and attach but I don't know where and how. Should I do it in the service layer in MessageService, UI layer, or maybe DAL layer where I have all my entities? Or should I redesign my solution and do the context logic in different place?
you appear to have the setup of context per window. that will have 2 impacts on how you maintain the objects within the context.
You do not want to pass objects from form to form. instead you will pass the ID(s) from form to form and load the entity within the context.
As an entity is updated within one context you will need to notify the other windows/contexts of the change so they can refresh their data.
here is an MSDN article detailing the process of context per form. The article uses NHibernate, but the process would be almost identical for EF and DbCotext
http://msdn.microsoft.com/en-us/magazine/ee819139.aspx
In the code below, I have a List object. I want to iterate through each one and assign a value to one of the properties on each Item object. To get the value, I need to call an async method of a WCF service.
When the call to my WCF service completes, how do I take that data and assign it to the current instance (i) in itemsList? Is there a way to access i from my xxxCompleted event?
private void SomeMethod()
{
List<Item> itemsList = GetItems();
foreach(Item i in itemsList)
{
MyClient client = new MyClient();
client.GetSomeValueCompleted += client_GetSomeValueCompleted;
client.GetSomeValueAsync(i.ID);
}
}
private void client_GetSomeValueCompleted(object sender, GetSomeValueEventArgs e)
{
int id = e.Result;
// how do I assign this ID to my itemsList object, i ???
}
You can pass the instance of MyClient class as the userstate on the async method call.
Take a look at this link
private void SomeMethod()
{
List itemsList = GetItems();
foreach(Item i in itemsList)
{
MyClient client = new MyClient();
client.GetSomeValueCompleted += client_GetSomeValueCompleted;
client.GetSomeValueAsync(i.ID, client);
}
}
private void client_GetSomeValueCompleted(object sender, GetSomeValueEventArgs e)
{
int id = e.Result;
// how do I assign this ID to my itemsList object, i ???
(e.UserState as MyClient).ID = id;
}