Continuam lucrul la aplicatia Simple Finance Manager.
In folder-ul App_Code vom crea trei fisiere .cs, fiecare reprezentand o clasa: Account, cu atributul Serializable,care va contine metode de incarcare a controalelor cu date, delegati pentru evenimente, Record care va incarca/salva efectiv inregistrarile, Settings care ne va ajuta la stabilirea unor setari ale aplicatiei.
Inregistrarile vor fi retinute intr-un xml, care se va salva in directorul aplicatiei. Vom retine ca date pentru o inregistrare: suma, data si un comentariu.Xml-ul este de forma:
<root> <record amount="8" RecordDate="05.05.2008 16:36:20"><![CDATA[&];&];&>;]]></record> <record amount="-1343" RecordDate="07.06.2009 22:43:45"><![CDATA[supermarket]]></record> <record amount="6" RecordDate="03.05.2010 16:06:45" /> </root>
In Main Window, apelam metoda InitItems(), care va popula controalele cu date.
/// <summary> /// populate the controls with data /// </summary> private void InitItems() { //get the path for the xml file string path = GetSaveFileFullPath(); account = new Account(); if (File.Exists(path)) { //load items.... account = LoadAccountData(path); } account.OnChanged += new Account.RecordEvent(account_OnChanged); var res = account.recordList; //clear the records lstRecords.Items.Clear(); //add in list from recordList foreach (var item in res) { lstRecords.Items.Add(item); } txtTotal.Text = account.TotalAmount.ToString(); }
Metoda GetSaveFileFullPath determina si returneaza calea aplicatiei care se executa in momentul curent. In cazul nostru, SFM.exe.
Codul pe care l-am scris este caracteristic Compact Framework:
string path = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
Metoda LoadAccountData va apela metoda Load a clasei Account si va returna un obiect de tip Account account a carei proprietate recordList va returna inregistrile.
Proprietatea recordList este o lista de tipul Record.
Metoda Load va primi ca parametru calea unde va crea documentul xml.
/// <summary> /// /// </summary> /// <param name="path"></param> public void Load(string path) { const string XPATH_RECORD = "root/record"; XmlDocument doc = new XmlDocument(); doc.Load(path); XmlNodeList records = doc.SelectNodes(XPATH_RECORD); m_list = new List<Record>(); if (records != null) { for (int i = 0; i < records.Count; i++) { Record r = Record.Load(records[i]); Add(r, false); //do not sort after each record } m_list.Sort(); } }
Alaturi de metoda InitItems(), la pornirea aplicatiei se apeleaza si metodele InitYears() si InitMonths().
Metoda InitYears va popula combobox-ul cu anii din inregistrari. Pentru acesta am creat metoda GetRecordsYears in clasa Account.
public string[] GetRecordsYears() { Dictionary<string, string> years = new Dictionary<string, string>(); //for each item of the list for (int i = 0; i < m_list.Count; i++) { years[m_list[i].RecordDate.Year.ToString()] = ""; } return years.Keys.ToArray<string>(); }
Metoda InitMonths va popula combobox-ul cu lunile. Ea va primi ca parametru un an si va returna lunile anului respectiv care contin inregistrari. In interiorul acesteia, se va apela metoda GetRecordsMounth din clasa Account.
public int[] GetRecordsMounth(int year) { Dictionary<int, string> mounths = new Dictionary<int, string>(); for (int i = 0; i < m_list.Count; i++) if (m_list[i].RecordDate.Year == year) mounths[m_list[i].RecordDate.Month] = ""; int[] m = mounths.Keys.ToArray(); Array.Sort(m); return m; }
Clasa Account mai contine si proprietatile:
Proprietatea TotalIN, de tip double, returneaza suma inregistrarilor efectuate cu plus, prin parcurgerea listei de inregistrari.
public double TotalIn { get { double total = 0; for (int i = 0; i < m_list.Count; i++) { if (m_list[i].Amount > 0) total += m_list[i].Amount; } return total; } }
Proprietatea pentru TotalOut, de tip Double, returneaza suma inregistrarilor efectuate cu minus, prin parcurgerea listei de inregisrari.
public double TotalOut { get { double total = 0; for (int i = 0; i < m_list.Count; i++) { if (m_list[i].Amount < 0) total += m_list[i].Amount; } return total; } }
Proprietatea TotalAmount, de tip Double, returneaza suma tuturor inregistrarilor, prin parcurgerea listei de inregistrari.
public double TotalAmount { get { double sum = 0; if (m_list == null) return sum; for (int i = 0; i < m_list.Count; i++) sum += m_list[i].Amount; return sum; } }
Clasa Record
Exista proprietati pentru fiecare informatie pe care dorim sa o salvam:
public double Amount { get; set; } public DateTime RecordDate { get; set; } public string Comment { get; set; }
Metoda de salvarea efectiva a xml-ului.
public void Save(XmlNode parentNode) { XmlNode rn = parentNode.OwnerDocument.CreateNode(XmlNodeType.Element, RECORD_SAVE_NODE, ""); //atribute for the amount XmlAttribute atrAmount = parentNode.OwnerDocument.CreateAttribute(RECORD_AMOUNT_ATR); atrAmount.Value = Amount.ToString(); //atribute for the date XmlAttribute atrDate = parentNode.OwnerDocument.CreateAttribute(RECORD_RECORDDATE_ATR); //new node for the comment if (Comment != null && Comment.Trim() != "") { XmlNode nodeComment = parentNode.OwnerDocument.CreateNode(XmlNodeType.CDATA, "", ""); nodeComment.InnerText = Comment.Replace("]]>", "&];&];&>;"); rn.AppendChild(nodeComment); } //insert the attributes rn.Attributes.Append(atrAmount); rn.Attributes.Append(atrDate); parentNode.AppendChild(rn); }
Metoda de incarcare a datelor Load(XmlNode node), ce va returna un obiect de tip Record , apelata in metoda Load a clasei Account. Codul citeste informatiile din Xml:
double amount = double.Parse(node.Attributes[RECORD_AMOUNT_ATR].Value); var value = node.Attributes[RECORD_RECORDDATE_ATR].Value; Record r = new Record(amount, date); if (node.InnerText != null && node.InnerText.Trim() != "") r.Comment = node.InnerText.Trim().Replace("&];&];&>;", "]]>"); return r;
Clasa Record mosteneste interfata IEnumerable:
#region IEnumerable Members public IEnumerator GetEnumerator() { return m_list.GetEnumerator(); } #endregion
Clasa Settings
Clasa Settings se "mapeaza" pe XML-ul Settings, care se salveaza tot in directorul aplicatiei. Acesta va retine numarul de telefon si email-ul catre care se vor trimite rapoartele. Valorile pot fi schimbate de utilizator in fereastra Generare Raport.
In constructor vom obtine calea unde se executa aplicatia si vom crea un fisier Settings.xml.
Vom folosi clasele XmlDocument, XmlElement, XmlNodeList si NameValueCollection.
// Add settings to the NameValueCollection. m_settings = new NameValueCollection(); m_settings.Add("Email", nodeList.Item(0).Attributes["value"].Value);
Clasa Settings va contine 2 proprietate statice, pentru numar de telefon si email. Ele sunt create in acelasi mod, asa ca vom arata doar codul pentru Email:
/// <summary> /// email property /// </summary> public static string Email { get { return m_settings.Get("Email"); } set { m_settings.Set("Email", value); } }
De asemenea, clasa va avea ca membru si o metoda de Update pentru actualizarea modificarilor.
In urmatorul articol vom instala aplicatia SFM pe telefon.