Практична робота 5

 

         Метою даної практичної роботи стане написання додатку, який буде керувати контактами користувача, тобто, користувач буде додавати туди своїх друзів із адресами, номерами телефонів і таке інше, а додаток буде дозволяти ці контакти переглядати, редагувати та видаляти. Ще, в даній програмі буде реалізована функція збереження контактів в файл .xml, тобто, Ви ще розглянете елементарні функції зчитування та запису даних в такі файли. Контакти у нас будуть зберігатися у вигляді списку допоміжного класу Person який оголошений в головній формі, і який окрім змінних в яких зберігаються дані контакту містить лише конструктор, який переносить його аргументи в ці змінні, і ще одну функцію, яка повертає всі дані контакту у формі рядка, який можна одразу ж додати в ListView.

         Для вищеописаного нам потрібно буде дві форми, перша (головна) буде безпосередньо відображати контакти та головне меню із параметрами і процедурами управління ними. Наведемо вигляд цього вікна із переліченими компонентами, які воно використовує.

Головне вікно та його компоненти

Підменю «Контакт»

Описание: C:\Users\Sergiy\AppData\Local\Temp\SNAGHTML16509071.PNG

Підменю «Вид» - «Стовпці»

         Також нам, ще потрібно вікно, яке візьме на себе редагування та створення контактів. Не будемо розділяти ці дві операції по різним вікнам. Перепишемо конструктор другого вікна так, щоб форма вже при створенні знала яку функцію їй потрібно реалізувати. Приведемо вигляд другої форми.

Описание: C:\Users\Sergiy\AppData\Local\Temp\SNAGHTML16544328.PNG

Форма додання/редагування контактів та її компоненти

         Тепер можемо перейти саме до програмної реалізації програми. Нижче буде приведений код головної форми.

public partial class Form1 : Form

 {

  public List<Person> contacts= new List<Person>(); //Список об’єктів типу Person, клас буде описаний нижче,

  //так, як для редактора с# першим у файлі мусить бути клас форми,

  //інакше візуальний редактор форм середовища буде відключено

  //ці змінні відповідають за необхідність відображення полів списку контактів

  public bool n; //поле імені

  public bool sn;//поле прізвища

  public bool mn;//поле по-батькові

  public bool p; //поле телефон

  public bool s; //поле скайп

  public bool a; //поле адреси

  public bool b; //поле дня народження

  public bool v; //поле вконтакте

 

  public void write_xml(){ //функція зберігає наш список об’єктів Person у файл contacts.xml

  //поточної директорії додатку

  XmlWriter w = XmlWriter.Create("contacts.xml"); //зв’язуємо файл із класом опрацювання .xml файлів

  w.WriteStartDocument();//починаємо писати файл (записуємо заголовки .xml документу)

  w.WriteStartElement("contacts");//формуємо секцію contacts

  foreach (Person p in contacts)//перебираємо всю нашу колекцію Person

   {

    w.WriteStartElement("contact");//починаємо одиничний елемент contact

    w.WriteElementString("name",p.name);//записуємо ім’я

    w.WriteElementString("second_name", p.sec_name);//записуємо прізвище

    w.WriteElementString("middle_name", p.mid_name);//записуємо по-батькові

    w.WriteElementString("phone", p.phone);//записуємо телефон

    w.WriteElementString("skype", p.skype);//записуємо скайп

    w.WriteElementString("adress", p.adress);//записуємо адресу

    w.WriteElementString("birthday", p.birthday);//записуємо день народження

    w.WriteElementString("vkontakte", p.vk_link);//записуємо вконтакте

    w.WriteEndElement();//завершуємо секцію contact

   }

  w.WriteEndElement();//завершуємо секцію contacts

  w.WriteEndDocument();//записуємо кінець документу

  w.Flush();//записуємо дані в файл, якщо вони частково зберігалися у кеші

 }

 

 public void read_xml()

  {//функція зчитує з файлу contacts.xml контакти, та формує список об’єктів Person

   XmlDocument r=new XmlDocument();//ініціалізуємо клас роботи із .xml файлами

   //для зручності оголосимо змінні для проміжного зберігання даних контакту

   string n=""; //для імені

   string sn="";//для прізвища

   string mn="";//для по-батькові

   string p=""; //для телефону

   string s=""; //для скайпу

   string a=""; //для адреси

   string b=""; //для дня народження

   string v=""; //для вконтакте

   r.Load("contacts.xml");//завантажуємо файл контактів

   foreach (XmlNode node in r.GetElementsByTagName("contact"))

    {//для всіх вузлів contact

     foreach (XmlNode ch in node.ChildNodes)

      { //зчитуємо дані контакту

       switch (ch.Name) { //будемо дивитися які дані контакту зчитали, і записувати у відповідну змінну

        case "name"://якщо ім’я

         n = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "second_name"://якщо прізвище

         sn = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "middle_name"://якщо по-батькові

         mn = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "phone"://якщо телефон

         p = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "adress"://якщо адреса

         a = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "skype"://якщо скайп

         s = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "birthday"://якщо день народження

         b = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

        case "vkontakte"://якщо вконтакте

         v = ch.InnerText;//записуємо в змінну

         break;//переходимо до слідуючого запису вузла contact

       }

      }

     contacts.Add(new Person(n, sn, mn, p, s, a, b, v));//додаємо в наш список контактів новий контакт

     //де n, sn, mn, p, s, a, b, v - поля контакту сформовані вище

    }

     show_contats();// показуємо контакти візуально на формі

  }

 

 public void show_contats() //процедура формує listView1 з контактами записаними в списку contacts

  {

   listView1.Items.Clear();//очищуємо елементи listView1

   ListViewItem li;//змінна для створення нового елементу списку listView

   foreach (Person pr in contacts) {//перебираємо всі контакти через змінну pr

    li=listView1.Items.Add(pr.name);//додаємо до listView новий елемент із першим стовпцем імені

    //додаємо всі інші стовпці нашого контакту використаємо метод, який буде описаний нижче

    //перший аргумент false - не передавати ім’я, так як стовпець із іменем вже створений

    //інші аргументи це змінні форми, які відповідають за відображення стовпців               

    li.SubItems.AddRange(pr.get_columns(false,sn,mn,p,s,a,b,v).ToArray());

    li.Tag = pr;//закріплюємо елемент ListViewItem із елементом із списку контактів

   }

   //автоматично розширюємо колонки listView1

   listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);//вміст елементів

   listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);//заголовки елементів

  }

 

 public void recreate_columns()//перезавантаження контактів, в залежності від обраних стовпців для відображення

  //наприклад коли користувач ввімкнув, або вимкнув той чи інший стовпець

  {

   //зчитуємо із головного меню стан відмічення елементів відображення стовпців

   n = nameToolStripMenuItem.Checked;//стовпець імені

   sn = secondNameToolStripMenuItem.Checked;//стовпець прізвища

   mn = midleNameToolStripMenuItem.Checked;//стовпець по-батькові

   p = phoneToolStripMenuItem.Checked;//стовпець телефон

   s = skypeToolStripMenuItem.Checked;//стовпець скайп

   a = adressToolStripMenuItem.Checked;//стовпець адреси

   b = birthdayToolStripMenuItem.Checked;//стовпець дня народження

   v = vkontakteToolStripMenuItem.Checked;//стовпець вконтакте

   listView1.Columns.Clear();//очищуємо всі елементи listView1

   //в залежності від відмічених стовпців, додаємо потрібні до компоненти listView1

   if (n) listView1.Columns.Add("Name");//стовпець ім’я

   if (sn) listView1.Columns.Add("Second Name");//стовпець прізвища

   if (mn) listView1.Columns.Add("Middle Name");//стовпець по-батькові

   if (p) listView1.Columns.Add("Phone");//стовпець телефон

   if (s) listView1.Columns.Add("Skype");//стовпець скайп

   if (a) listView1.Columns.Add("Adress");//стовпець адреси

   if (b) listView1.Columns.Add("Birthday");//стовпець дня народження

   if (v) listView1.Columns.Add("VKontakte Link");//стовпець вконтакте

   show_contats();//відображаємо контакти

  }

 

 public Form1()//конструктор форми

  {

   InitializeComponent();

   recreate_columns();//перестворюємо елементи контактів в listView1

  }

 

 private void nameToolStripMenuItem_Click(object sender, EventArgs e)//обробник елементу відображення стовпця імені

  {

   recreate_columns();//перестворюємо елементи контактів в listView1

  }

 

 private void newToolStripMenuItem_Click(object sender, EventArgs e)//обробник елементу головного меню контакт-створити

  {

   Form2 f2 = new Form2(this);//створюємо екземпляр другої форми

   f2.ShowDialog();//відображаємо другу форму модально

  }

 

 private void deleteToolStripMenuItem_Click(object sender, EventArgs e)//обробник елементу головного меню контакт-видалити

  {

   foreach (int ind in listView1.SelectedIndices)//перебираємо всі індекси вибраних елементів listView1

   //через змінну ind

   contacts.RemoveAt(ind);//видаляємо вибраний елемент із списку контактів

   show_contats();//відображаємо контакти

  }

 

 private void editToolStripMenuItem_Click(object sender, EventArgs e)//обробник елементу головного меню контакт-редагувати

  {

   int sel=-1;//оголошуємо змінну для зручності, в ній ми будемо зберігати вибраний елемент, або -1

   foreach (int ind in listView1.SelectedIndices)//вибераємо останній із вибраних елементів

    sel = ind;//якщо такі є

   if (sel != -1)//якщо все таки є вибраний елемент

    {

     //створюємо екземпляр другої форми

     //і передаємо значення всіх стовпців для редагування, та індекс вибраного елементу

     Form2 f2 = new Form2(this, contacts[sel].name, contacts[sel].sec_name, contacts[sel].mid_name, contacts[sel].phone, contacts[sel].skype, contacts[sel].adress, contacts[sel].birthday, contacts[sel].vk_link, sel);

     f2.ShowDialog();//показуємо вікно модально

    }

  }

 

 private void Form1_FormClosing(object sender, FormClosingEventArgs e)//подія закриття форми

  {

   write_xml();//зберігаємо наш список контактів в файл

  }

 

 private void Form1_Shown(object sender, EventArgs e)//подія показу форми

  {

   read_xml();//зчитуємо список контактів із файлу

  }

 

 private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)//обробник подвійного натиску лівої кнопки миші

 //по компоненту listView1

  {

   Person pr;//змінна для зручності

   foreach (int ind in listView1.SelectedIndices) { //перебираємо всі вибрані елементи

   pr = (Person)listView1.Items[ind].Tag;//зв’язуємо нашу змінну pr з об’єктом який вибраний через Tag

   System.Diagnostics.Process.Start(pr.vk_link);//переходимо за посиланням в стовпці вконтакте

  }

 }

}

 

public class Person //оголошення допоміжного класу, який використовується для зберігання інформації про контакт

 {

  public string name;//для збереження імені

  public string sec_name;//для збереження прізвища

  public string mid_name;//для збереження по-батькові

  public string phone;//для збереження телефону

  public string skype;//для збереження скайпу

  public string adress;//для збереження адреси

  public string birthday;//для збереження дня народження

  public string vk_link;//для збереження вконтакте

 

  public Person(string n, string sn, string mn, string p, string s, string a, string b, string v)

   //конструктор класу, як параметри передаються по порядку всі дані контакту

   {

    //присвоюємо передані на м дані контакту в наші елементи класу

    name = n;

    sec_name = sn;

    mid_name = mn;

    phone = p;

    skype = s;

    adress = a;

    birthday = b;

    vk_link = v;

   }

 

  public List<string> get_columns(bool n, bool sn, bool mn, bool p, bool s, bool a, bool b, bool v)

   //повертаємо всі поля контакту в форматі списку рядків,

   //для зручності при додаванні контактів в listView

   {

    var t = new List<string>();//оголошуємо новий елемент списку

    if (n) t.Add(name);//додаємо ім’я

    if (sn) t.Add(sec_name);//додаємо прізвище

    if (mn) t.Add(mid_name);//додаємо по-батькові

    if (p) t.Add(phone);//додаємо телефон

    if (s) t.Add(skype);//додаємо скайп

    if (a) t.Add(adress);//додаємо адресу

    if (b) t.Add(birthday);//додаємо день народження

    if (v) t.Add(vk_link);//додаємо вконтакте

    return t;//додаємо створений елемент до списку

   }

}

         Тепер наведемо код другої форми для додання/редагування контактів.

public partial class Form2 : Form

 {

  public int contact_index;//змінна для збереження індексу виділеного контакту

  public Form1 f;//змінна для збереження посилання на першу форму

 

  public Form2(Form1 f1,string n="",string sn="",string mn="",string p="",string s="",string a="",string b="",string v="",int cn=-1)

   //конструктор форми

   //із обов’язкового потрібно передати лише посилання на головну форму

   //інші аргументи - поля контактів

   //та вибраний індекс - необов’язкові

   //і якщо форма має додати новий контакт, їх передавати не треба

   {

    InitializeComponent();

    textBox1.Text = n;//переносимо в поле вводу імя

    textBox2.Text = sn;//переносимо в поле вводу прізвище

    textBox3.Text = mn;//переносимо в поле вводу по-батькові

    textBox4.Text = p;//переносимо в поле вводу телефон

    textBox5.Text = s;//переносимо в поле вводу скайп

    textBox6.Text = a;//переносимо в поле вводу адресу

    textBox7.Text = b;//переносимо в поле вводу день народження

    textBox8.Text = v;//переносимо в поле вводу вконтакте

    contact_index = cn;//індекс вибраного контакту

    f = f1;//посилання на головну форму

   }

 

  private void button2_Click(object sender, EventArgs e) //обробник кнопки приховати

   {

    Close();//закриваємо форму

   }

 

  private void button1_Click(object sender, EventArgs e)//обробник кнопки ок

  {

   if (contact_index == -1) {//якщо індекс обраного контакту -1, тобто форма викликана для додання нового контакту

   //додаємо до списку контактів головної форми новий контакт, який базується на полях

   //вводу цієї форми

    f.contacts.Add(new Person(textBox1.Text,textBox2.Text,textBox3.Text,textBox4.Text,textBox5.Text,textBox6.Text,textBox7.Text,textBox8.Text));

    f.show_contats();//відображуємо контакти на головній формі   

   } else { //якщо форма викликана для редагування контакту

    //створюємо новий екземпляр контакту Person

    //на базі введених текстових полів форми

    Person p = new Person(textBox1.Text, textBox2.Text, textBox3.Text, textBox4.Text, textBox5.Text, textBox6.Text, textBox7.Text, textBox8.Text);

    f.contacts[contact_index] = p;//замінюємо вибраний контакт новоствореним

    f.show_contats();//відображуємо контакти на головній формі  

   }

    Close();//закриваємо форму

  }

}

         Ось і кінець прикладу, для отримання позитивної оцінки за практичну роботу Вам потрібно буде ще доробити декілька додаткових пунктів, наведених нижче.

·        Всі англійські написи потрібно перевести на український

·        Створити пункт про програму в головному меню

·        Додати до головного меню пункт вийти із програми

·        При виході із додатку виводити повідомлення «Ви дійсно бажаєте вийти?» і закривати додаток лише коли користувач натиснув «Так»

·        Додати до контакту стовпець, який відображає лінк в фейсбук (також потрібно стовпець зберігати у файл контактів, та реалізувати функціє його редагування)

·        Додати до контакту стовпець, який відображає лінк в твітер (також потрібно стовпець зберігати у файл контактів, та реалізувати функціє його редагування)

·        Реалізувати механізм, і елементи в головному меню, які будуть приховувати стовпці фейсбуку і твітеру

·        Додати до головного меню підменю, в якому можна вибрати за посиланням в якому стовпці переходити при подвійному кліку миші (вконтакте, фейсбук, твітер). Один із варіантів реалізації - може бути вибором елементу підменю, так як реалізовано підменю відображення стовпців