Työaikaseuranta (GTK)
Näissä ohjeissa tuotetaan Työaikaraportille GTK-käyttöliittymä. Muista vaihtoehdoista katso Työaikaseurannan esittelysivu.
Oletuksena on, että Työaikaraportti on tehtynä, sillä sen aliohjelmia käytetään tässä.
Työaikaseuranta lukee kaksi tiedostoa (projektit.txt
ja nykproj.txt
) ja tuottaa kaksi tiedostoa (ajat.txt
ja nykproj.txt
).
Linkkejä
- Työaikaraportin suunnitelmasivu
- Työaikaraportin tutoriaalisivu
- Tämän ohjelman (Työaikaseuranta) suunnitelmasivu
- Työaikaseurannan esittelysivu (täällä vaihtoehdot WPF:lle)
- Xamarinin editoriin Visual Studio 2017 Blue -tyyli (ei pakollinen, voi halutessaan myös tehdä itse sellaisen kuin tykkää tai valita monista valmiista vaihtoehdoita)
Tavoite ja lopputulos
Ohjelmassa voi valita pudotusvalikosta työskentelyn kohteena olevan pää- ja aliprojektin, jotka ohjelma etsii projektit.txt
-tiedostosta.
Ajanoton voi käynnistää ja lopettaa työskentelyn ajat.txt
-tiedostoon, mikäli ajat ovat hyväksyttävässä muodossa. Ajan voi myös "unohtaa" -painikkeella, tai ajanottoa jatkaa -painikkeella.
Ohjelma osaa myös näyttää Työaikaraportin tekemän siistin raportin, joka aukeaa Tiedosto
-valikosta. Auki oleva pää- ja aliprojekti tallennetaan nykproj.txt
-tiedostoon, niin että ohjelmaa käynnistettäessä pudotusvalikoissa on valmiiksi valittuna viimeksi valittu projektikokonaisuus.
video ja kuva valmiista ohjelmasta.
Suunitelmakin pitää muuten tehdä, sinne ne kuvat voi piirtää kynällä ja paperilla.
—Voiko se suunnitelma olla sama kaikille alustoille?
VL: ilman muuta. Suunnitelmasa ei oikeastan edes mietitä alustaa. Eikä suunitelma sido lopullists toteutusta jos jotakin huomaa että on pakko tehdä eri lailla tai joskus jopa paremmin :-)
video
Kuvatkaa tähän video. Encoderin nauhoittaessa ei voi käyttää painikkeita.
—1. Aloitus
1.1 Uuden projektin luominen
Valitse Xamarinissa New Solution.../Other/.NET/Gtk# 2.0 Project
. Luo uusi projekti.
Xamarinin editorin asetuksia voi muokata Tools/Options.../Text Editor/Syntax Highlighting
. Videolla käytetyn VS2017-tyylin voit ladata tästä.
Otetaan Työaikaraportin attribuutit ja staattiset funktiot koodiimme. Otetaan seuraavat asiat käyttöön koodin alussa:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
using System.IO;
using System.Text;
using Gtk;
using Pango;
1.2 Pohjataulukko GUIhin
Saamme käyttöliittymäeditorin auki alalaidan Designer
-välilehdestä. (Takaisin koodiin pääsee Source
-välilehdestä.
Valitaan MainWindow
ylälaidassa olevasta pudotusvalikosta. Voimme Visual Studion tavoin avata Properties
- ja Toolbox
-ikkunat View
-valikosta. Etsitään toolboxista table
ja raahataan se nyt aktiivisena olevan MainWindow
-kontrollin päälle, tehden siitä tämän lapsiolion.
Tämän uuden taulukon ollessa valittuna Properties
-ikkunan Table Properties
-kohdasta voidaan säätää rivien ja kolumnien määrää. Tehdään tästä 1x6-kokoinen taulukko.
2. GUIn rakentaminen
Annetaan ikkunassa olevan 1x6-taulukon nimeksi tablePohja
(videolla pohjataulukko
).
Lisätään toiseen ja kolmanteen riviin ComboBox
-kontrollit comboBoxPaaprojektivalikko
ja comboBoxAliprojektivalikko
, ja neljänteen Label
labelIlmoitus
, jonka tekstiksi voidaan vaihtaa jotain kuvaavaa.
Lisätään kahteen alimpaan riviin Table
-taulukot tableAloitus
ja tableLopetus
(videolla aloitustaulukko
ja lopetustaulukko
) ja asetetaan näiden ko'oiksi 2x1 ja 3x4.
Laitetaan ylimpään riviin MenuBar
, jota klikkaamalla voimme lisätä menun. Lisätään "Tiedosto"-menu, jonne lisätään Action
"Raportti" ja "Poistu"
Lisätään tableAloitus
-taulukkoon - ja -painikkeet buttonAloita
ja buttonLopeta
.
Lisätään tableAloitus
-taulukon kolmen ensimmäisen rivin ensimmäiseen kolumniin "Alku"-, "Loppu"- ja "Kommentti"-Label
, sekä toiseen kolumniin Entry
-tekstikentät entryAlku
, entryLoppu
ja entryKommentti
. Näiden Table Child Layout
-asetuksista asetetaan LeftAttach
=1 ja RightAttach
=3, jolloin tekstikentät venyvät ensimmäisen kolumnin oikeasta laidasta kolmennen kolumnin oikeaan laitaan. Lisätään viimeiselle riville vielä -, - ja -painikkeet buttonTallenna
, buttonPoista
ja buttonPeruuta
.
3. Toiminnallisuutta GUIhin
3.1 Tapahtumakäsittelijät painikkeisiin
Lisätään Properties
-ikkunan Signals/Button_Signals/Clicked
-kohtaan Aloita_Click
. Tämä generoi meille uuden aliohjelman:
protected void Aloita_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
Tähän voimme lisätä painikkeen disabloinnin ja
-painikkeen enabloinnin. (Poistetaan virheheitto!) buttonAloita.Sensitive = false;
buttonLopeta.Sensitive = true;
Tehdään vastaava mutta päinvastainen
-painikkeelle. protected void Lopeta_Click(object sender, EventArgs e)
{
buttonAloita.Sensitive = true;
buttonLopeta.Sensitive = false;
}
Meillä on nyt ohjelma, jonka kaksi keskimmäistä painiketta "väistelevät" vuorotellen. (Videolla painikkeet eivät nauhoituksen vuoksi toimi.)
Voidaan luoda kaikille muillekin kontrolleille tässä vaiheessa tyhjät tapahtumakäsittelijät.
4. Alueiden näkyvyydet
4.1 Näkyvyyksien asettaminen
Ohjelmassame on tällä hetkellä kaksi aluetta. Tulevaisuutta silmällä pitäen kannattaa jo tässä vaiheessa kuitenkin tehdä alueiden näkyvyyksien vaihtamisesta sellainen, että se toimii useammallakin alueella. Tämän voisi toteuttaa aliohjelmalla, joka piilottaisi kaikki muut paitsi parametrina saamansa alueen.
Luodaan attribuutiksi uusi lista
private List<Table> tablet = new List<Table>();
Lisätään kaikki kaksi aluetta tähän listaan pääohjelman sisällä.
public MainWindow()
: base(Gtk.WindowType.Toplevel)
{
Build();
tablet.Add(tableAloitus); tablet.Add(tableLopetus);
}
Kirjoitetaan Lopeta_Click
-aliohjelman sisään uusi aliohjelmakutsu, jolle viedään parametrina näkyväksi jäävä alue.
protected void Lopeta_Click(object sender, EventArgs e)
{
buttonAloita.Sensitive = true;
buttonLopeta.Sensitive = false;
VaihdaNakyvyysalue(tableLopetus);
}
Luodaan tällainen aliohjelma (luonnollisesti dokumentointeineen). Käydään foreach
-silmukalla tablet
-listaa läpi.
private void VaihdaNakyvyysalue(Table alue)
{
foreach (Table table in tablet)
{
}
}
Kun alue
on sama kuin table
, vaihdetaan sen lapsiolioiden näkyvyys näkyväksi, ja muulloin piilotetuksi.
foreach (Table table in tablet)
{
if ( table.Equals(alue) ) table.ChildVisible = true;
else table.ChildVisible = false;
}
Asetetaan vielä pääohjelmassa näkyvyysalueeksi tableAloitus
, jotta tableLopetus
ei näkyisi ohjelmaa käynnistettäessä.
public MainWindow()
: base(Gtk.WindowType.Toplevel)
{
...
VaihdaNakyvyysalue(tableAloitus);
}
Voidaan myös initiaalisesti disabloida buttonLopeta.Sensitive=false
) tai käyttöliittymäeditorissa (Common Widget Properties/Sensitive
ruksi pois).
Tehdään vastaava vielä muille painikkeille.
/// <summary> Tallenna-painikkeen painallus ...
protected void Tallenna_Click(object sender, EventArgs e)
{
VaihdaNakyvyysalue(tableAloitus);
}
/// <summary> Poista-painikkeen painallus ...
protected void Poista_Click(object sender, EventArgs e)
{
VaihdaNakyvyysalue(tableAloitus);
}
/// <summary> Peruuta-painikkeen painallus ...
protected void Peruuta_Click(object sender, EventArgs e)
{
VaihdaNakyvyysalue(tableAloitus);
buttonAloita.Sensitive = false;
buttonLopeta.Sensitive = true;
}
5. Pudotusvalikot
5.1 Pääprojektit pudotusvalikkoon
Lisätään aluksi projektit.txt
työskentelykansioon, jotta pääsemme lukemaan tiedostoa.
Luodaan pääohjelmaan uusi aliohjelmakutsu LuoValikko()
ja luodaan tynkä. Lisätään uusi attribuutti
private string[] projektitKaikki;
ja luetaan siihen projektit.txt
/// <summary>
/// Lukee tiedostosta projektien nimet ja tuottaa niistä pudotusvalikon vaihtoehdot
/// sekä asettaa viimeksi valitun projektin oletusprojektiksi
/// </summary>
private void LuoValikko()
{
projektitKaikki = File.ReadAllLines(PROJEKTIPOLKU);
}
Käytetään nyt jo olemassaolevaa aliohjelmaamme HaePaaprojektit
ja tuotetaan lista pääprojekteista. Laitetaan tämän listan sisältä comboBoxPaaprojektit
-pudotusvalikon sisällöksi.
List<string> paaprojektit = HaePaaprojektit(projektitKaikki);
foreach (string pp in paaprojektit) comboBoxPaaprojektit.Items.Add(pp);
(Huomaa, että Paaprojektivalikko_Changed
ei saa enää sisältää virheheittoa, tai ohjelman suoritus keskeytyy.)
Nyt pudotusvalikon sisältö toimii, mutta ennen sen avaamista näkyy vain tyhjää. Voimme asettaa ensimmäisen alkion "valituksi" alkioksi.
comboBoxPaaprojektivalikko.Active = paaprojektit.IndexOf(paaprojektit[0]);
5.2 Aliprojektit pudotusvalikkoon
Aliprojektien lisääminen on siinä mielessä vaikeampaa, että aliprojektipudotusvalikon sisältöä täytyy muuttaa joka kerta kun pääprojektia vaihdetaan.
Tehdään pääprojektipudotusvalikon tapahtumakäsittelijän sisälle uusi aliohjelmakutsu.
private void Paaprojektivalikko_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
VaihdaPaaprojektia();
}
Luodaan tällainen VaihdaPaaprojektia
-aliohjelma ja tallennetaan uuteen muuttujaan valittu pääprojekti.
private void VaihdaPaaprojektia()
{
string valittuPaaprojekti = comboBoxPaaprojektit.SelectedItem.ToString();
}
Käytetään taas valmista aliohjelmaa HaeAliprojektit
ja tallennetaan valitun pääprojektin aliprojektit paikallisesti listaan ja lisätään ne vastaavasti aliprojektipudotusvalikkoon.
List<string> valitunAliprojektit = HaeAliprojektit(projektitKaikki, valittuProjekti);
foreach (string aliprojekti in valitunAliprojektit)
comboBoxAliprojektivalikko.AppendText(aliprojekti);
comboBoxAliprojektivalikko.Active = 0;
Mutta tässä käy huonosti! Nyt pääprojektia vaihtaessa edellisen pääprojektin aliprojektit jäävät kummittelemaan aliprojektipudotusvalikkoon.
Tyhjennetään tämän estämiseksi aliprojektipudotusvalikon alkiot ennen uusien alkioiden lisäämistä.
private void VaihdaPaaprojektia()
{
string valittuProjekti = comboBoxPaaprojektivalikko.ActiveText;
List<string> valitunAliprojektit = HaeAliprojektit(projektitKaikki, valittuProjekti);
TyhjennaComboBox(comboBoxAliprojektivalikko);
foreach (string aliprojekti in valitunAliprojektit)
comboBoxAliprojektivalikko.AppendText(aliprojekti);
comboBoxAliprojektivalikko.Active = 0;
}
Valitettavasti GTK:ssa ComboBox.Clear
ei WPF:n tavoin oikeasti hävitä lapsiolioita. Tähän tarvitsemme uuden mystisen aliohjelman TyhjennaComboBox
, jonka toimintaan ei tässä tutoriaalissa sen syvällisemmin perehdytä.
private void TyhjennaComboBox(ComboBox cb)
{
cb.Clear();
CellRendererText cell = new CellRendererText();
cb.PackStart(cell, false);
cb.AddAttribute(cell, "text", 0);
ListStore store = new ListStore(typeof (string));
cb.Model = store;
}
6. Toiminnallisuuttaa ohjelmaan
6.1 Ajanoton lisääminen
Mitä ajan ottaminen tarkoittaa? Fundamentaalisesti kulunut aika on lopetus- ja aloitusajan erotus. Meidän ei siis tarvitsi käynnistää mitään kelloa systeemin sisällä, vaan riittää että otamme ylös kaksi "nykyhetkeä" ja laskemme niiden välisen erotuksen.
Halutaan siis tallentaa "nykyhetki" DateTime
-muuttujaan -napin painalluksesta.
Voisimme lisätä DateTime
-attribuutin ohjelmaan, mutta koska haluamme ajan näkyviin käyttöliittymään (ainakin jossain vaiheessa), voimme tallentaa sen jo nyt sinne ja kaivaa sen sieltä myöhemmin.
Nyt voimme lisätä Aloita_Click
-aliohjelman sisälle nykyhetken tallennuksen entryAlku
-kentän tekstiksi.
entryAlku.Text = DateTime.Now.ToString();
Sama tehdään Lopeta_Click
-aliohjelmalle.
entryLoppu.Text = DateTime.Now.ToString();
6.2 Tietojen tallentaminen tiedostoon
Haluamme siis tallentaa ajat.txt
-tiedostoon seuraavat tiedot:
pääprojekti|aliprojekti|aloitusaika|lopetusaika|kesto|kommentti
Pää- ja aliprojektien nimet ovat
-painiketta painaessa pudotusvalikoiden valitut objektit. Aloitus- ja lopetusajat löytyvät tekstikentistä, kuten myös mahdollinen kommentti. Meillä on siis tässä vaiheessa kestoa vaille kaikki tiedot.Muutetaan Tallenna_Click
-aliohjelmassa ajat string
-muodosta takaisin DateTime
-muotoon.
DateTime aloitusaika = DateTime.Parse(entryAlku.Text);
DateTime lopetusaika = DateTime.Parse(entryLoppu.Text);
Tehdään näiden rivien jälkeen uusi aliohjelmakutsu tiedot tallentavalle aliohjelmalle, jolle viedään parametrina kaikki em. tiedot kestoa lukuunottamatta.
TallennaTiedot(comboBoxPaaprojektivalikko.ActiveText,
comboBoxAliprojektivalikko.ActiveText, aloitusaika, lopetusaika, kommentti);
Luodaan tällainen aliohjelma.
public static void TallennaTiedot(string paaprojekti, string aliprojekti,
DateTime aloitusaika, DateTime lopetusaika, string komentti)
{
}
Kuluneen ajan saamme laskettua vähentämällä lopetusajasta aloitusajan. Tämä onnistuu kätevästi DateTime
-tyypin sisäänrakennetuilla funktioilla.
TimeSpan kulunutAika = lopetusaika.Subtract(aloitusaika);
Ylläoleva on yleismaallinen tapa laskea kesto. Koska C#-kielessä niin funktioita kuin operaattoreitakin voi kuormittaa (engl. overload), myös
TimeSpan kulunutAika = lopetusaika - aloitusaika;
tuottaisi saman lopputuloksen.
Luodaan tallenneteksti, jossa data on halutussa muodossa tolpilla eroteltuna, lopussa rivinvaihto
string tallenneteksti = paaprojekti + "|" + aliprojekti + "|" +
aloitusaika.ToString() + "|" + lopetusaika.ToString() + "|" +
kulunutAika.ToString() + "|" + komentti + Environment.NewLine;
Kirjoitetaan tämä tiedostoon vanhan tekstin jatkeeksi.
File.AppendAllText(AIKAPOLKU, tallenneteksti);
Ilmeisesti em. komento toimii, vaikkei tiedostoa olisi vielä olemassa.
Tässä vaiheessa saatetaan huomata, että edellisen tallennuksen kommentit jäävät kummitelemaan tekstikenttään. Muokataan Tallenna_Click
-aliohjelmaa vielä niin, että kommenttikenttä tyhjenee tallentaessa.
string kommentti = textBoxKommentti.Text;
entryKommentti.Text = "";
TallennaTiedot(comboBoxPaaprojektit.SelectedItem.ToString(), ... , kommentti);
Huomataan myös, että ohjelma kaatuu mikäli käyttäjä muokkaa aloitus- tai lopetusaikaa virheelliseen muotoon. Ympäröidään tämä kohta try-catch
-silmukalla. (Huomaa, että muuttujien esittely täytyy tehdä silmukan ulkopuolella.)
DateTime aloitusaika;
DateTime lopetusaika;
try
{
aloitusaika = DateTime.Parse(entryAlku.Text);
lopetusaika = DateTime.Parse(entryLoppu.Text);
}
catch (System.FormatException)
{
labelIlmoitus.Text = "Kirjoita ajat oikeassa muodossa!";
return;
}
VaihdaNakyvyysalue(tableAloitus);
6.3 Tallennetun tiedon näyttäminen
Tietojen tallentuessa onnistuneesti voisimme myös näyttää ilmoitustekstinä tämän tiedon.
Miten saamme kuluneen ajan näytettyä? Kulunut aikahan laskettiin TallennaTiedot
-aliohjelmassa. Tämä aliohjelma on kuitenkin staattinen, joten se ei voi sorkkia tekstikenttiä. Muokataan aliohjelmasta seuraavaksi sellainen, että se palauttaa ilmoitusviestin.
Muokataan Tallenna_Click
-aliohjelmaan ilmoitustekstin näyttäminen entryIlmoitus
-kentässä TallennaTiedot
-aliohjelman paluuarvona.
labelIlmoitus.Text = TallennaTiedot(comboBoxPaaprojektivalikko.ActiveText, ...)
Muokataan TallennaTiedot
-aliohjelma palauttamaan merkkijonon.
public static string TallennaTiedot(string paaprojekti, ...)
{
TimeSpan kulunutAika = lopetusaika.Subtract(aloitusaika);
...
return "Projektiin " + paaprojekti + " käytetty aika: " + kulunutAika.ToString();
}
7. Raportin näyttäminen
7.1 Raportti uudessa ikkunassa
Raportti näytetään "Tiedosto"-menun kohdasta "Raportti", jonka tapahtumakäsittelijä on Raportti_Activated
. Luetaan täällä projektit
ja ajat
, ja tallennetaan raportti
-merkkijonoon Raportoi
-aliohjelman paluuarvo.
protected void Raportti_Activated(object sender, EventArgs e)
{
string[] projektit = File.ReadAllLines(PROJEKTIPOLKU);
string[] ajat = File.ReadAllLines(AIKAPOLKU);
string raportti = Raportoi(projektit, ajat);
}
Luodaan tämän jälkeen aluksi tyhjä dialogi (Dialog
).
Dialog dialogi = null;
Luodaan uusi tekstinnäyttökenttä (TextView
). Tämä on kuin Entry
, mutta voi olla monirivinen (ja sen tekstisisältö TextView.Buffer.Text
). Tallennetaan sen tekstiksi raportti
.
TextView textViewRaportti = new TextView();
textViewRaportti.Buffer.Text = raportti;
Kirjoitetaan uusi try-finally
-lohko, jonka päätteeksi dialogi tuhotaan.
try
{
}
finally
{
if (dialogi != null) dialogi.Destroy ();
}
GTK:n Dialog
ottaa ottaa parametreina otsikon, isännän (engl. parent), DialogFlags
-ominaisuudet ja taulukon painikkeiden tiedoista (otsikko ja toimintotyyppi). Luodaan try
-lohkon sisään uusi Dialog dialogi
.
try
{
dialogi = new Dialog("Raportti", this,
DialogFlags.DestroyWithParent | DialogFlags.Modal,
"Sulje", ResponseType.Close);
}
Syntyvän dialogin otsikoksi tulee siis "Raportti", ja sen isäntä on this
(joka tässä tapauksessa on ohjelman pääikkuna MainWindow
). Isännän tuhoutuessa myös dialogi tuhotaan, ja dialogi on modaalinen (jättää disabloidun pääikkunan näkymään). Lisäksi luodaan painike , jonka toimintotyyppi on Close
(sulje).
Lisätään lohkon sisällä vielä dialogin vertikaaliseen sisältölaatikkoon (VBox
) aiemmin luomamme textViewRaportti
, näytetään kaikki dialogin sisältö ja käynnistetään dialogi
.
dialogi.VBox.Add(textViewRaportti);
dialogi.ShowAll();
dialogi.Run();
Uusi ikkuna avautuu nyt valikosta hienosti, mutta nimet ja luvut rivittyvät rumasti. Tämä johtuu siitä ettei oletusfontti ole tasalevyistä (engl. monospaced). Tasalevyisessä fontissa kaikki merkit ovat yhtä leveitä, jolloin merkit ovat nätisti "ruudukossa". Suosittu tasalevyinen fontto on esimerkiksi Courier New
. Asetetaan tämä textViewRaportti
-tekstinnäyttökentän fontiksi.
textViewRaportti.ModifyFont(FontDescription.FromString("Courier new"));
8. Valitun projektin muistaminen
8.1 Nykyisten projektien tallentaminen tiedostoon
Tahdomme ohjelmasta sellaisen, että ohjelma "muistaa" mikä projektikokonaisuus on ollut viimeksi valittuna. Jos projekteja on paljon, tämä on kätevä ominaisuus, sillä ohjelman voi tällöin huoletta sulkea, ja ensi kerran avatessa voi ajastaa taas edellistä projektia nopeasti.
Tehdään tätä varten uusi tiedosto, johon tallennetaan pää- ja aliprojekti. Luodaan pääluokan attribuutiksi tämän tiedoston polku.
private const string NYKPROJPOLKU = "nykproj.txt";
Mihin kohtaan koodia tämän tiedoston muokkaaminen pitäisi lisätä? Meidän ei välttämättä ole tarpeen muokata nykyisen pää- ja aliprojektin tietoja erikseen, sillä ne kulkevat aina yhtenä kokonaisuutena. Koska pääprojektin vaihtaminen vaihtaa nykyisellään aina myös aliprojektin, voimme suorittaa tiedostoon tallennuksen aliprojektia vaihtaessa.
Kutsutaan aliprojektivalikon tapahtumakäsittelijästä uutta aliohjelmaa VaihdaAliprojektia
.
private void Aliprojektivalikko_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
VaihdaAliprojektia();
}
Luodaan tällainen aliohjelma, jossa tallennetaan merkkijonoon valitutProjektit
pudotusvalikoiden valitut projektit rivinvaihdolla erotettuna.
private void VaihdaAliprojektia()
{
string valitutprojektit = comboBoxPaaprojektivalikko.ActiveText + Environment.NewLine +
comboBoxAliprojektivalikko.ActiveText;
}
Kirjoitetaan lopuksi valitutProjektit
tiedostoon. File.WriteAllText
korvaa surutta kaiken aiemman tiedostossa olevan.
File.WriteAllText(NYKPROJPOLKU, valitutprojektit);
8.2 Tallennettujen projektien lukeminen
Seuraavaksi vaihdetaan ohjelman käynnistyessä pudotusvalikoiden valitut projektit tallennettuihin.
Luetaan luotu tiedosto ohjelman käynnistyksen yhteydessä suoritettavassa LuoValikko
-aliohjelmassa.
string[] valitutProjektit = File.ReadAllLines(NYKPROJPOLKU);
Tässäkin tapauksessa kannattaa ennen tiedoston lukemisen yrittämistä varautua tiedoston puuttumiseen.
if (!File.Exists(NYKPROJPOLKU)) return;
ComboBox.Active
ottaa parametrina näytettävän tekstin indeksin. Saamme tämän kaivettua paaprojektit
-listasta.
comboBoxPaaprojektivalikko.Active = paaprojektit.IndexOf(valitutprojektit[0]);
Aliprojekteja varten on aliprojektit ensin haettava omaan listaan.
List<string> aliprojektit = HaeAliprojektit(projektitKaikki, valitutprojektit[0]);
comboBoxAliprojektivalikko.Active = aliprojektit.IndexOf(valitutprojektit[1]);
Mutta tämä ei toimi. Nykyisellään pää- ja aliprojekteiksi tulee edelleen ensimmäiset pää- ja aliprojektit, vaikka tiedostoon tallentuukin vaihdetut projektit.
Miten ongelmaa lähteä ratkaisemaan? Videolla laitetaan keskeytyskohta valitutProjektit
-tiedoston lukemiseen ja huomataan, että tiedosto on muuttunut tallentamisen jälkeen. Tämä tarkoittaa sitä, että jossakin aiemmassa vaiheessa koodia tiedostoa on sorkittu. Jos muu ei auta, lähde etsimään riviä askel kerrallaan debuggaamalla.
Ongelmakohtaa löytyy tässä tapauksessa pari riviä ylempää, missä paaprojektit
-listan ensimmäinen alkio asetetaan pääprojektipudotusvalikon valituksi projektiksi. Poistetaan tämä rivi.
private void LuoValikko()
{
projektitKaikki = File.ReadAllLines(PROJEKTIPOLKU);
List<string> paaprojektit = HaePaaprojektit(projektitKaikki);
foreach (string pp in paaprojektit) comboBoxPaaprojektivalikko.AppendText(pp);
// POISTA // comboBoxPaaprojektivalikko.Active = paaprojektit.IndexOf(paaprojektit[0]);
if ( !File.Exists(NYKPROJPOLKU) ) return;
string[] valitutprojektit = File.ReadAllLines(NYKPROJPOLKU);
comboBoxPaaprojektivalikko.Active = paaprojektit.IndexOf(valitutprojektit[0]);
List<string> aliprojektit = HaeAliprojektit(projektitKaikki, valitutprojektit[0]);
comboBoxAliprojektivalikko.Active = aliprojektit.IndexOf(valitutprojektit[1]);
}
9. Viimeistely
9.1 Ulkoasullista hienosäätöä
Ohjelmamme avautuvan ikkunan otsikko on tälle hetkellä "MainWindow". Voimme muuttaa tätä desginerissä valitsemalla MainWindow
kohdasta Window Properties/Title
.
9.2 Reunuksista
Oikea ja vasen laita ovat tällä hetkellä rumasti kiinni tai pitkällä irti ikkunan laidoista. Voimme säätää hiirellä ikkunan oikean kokoisiksi ja asettaa kontrollien reunuksia paremmaksi kohdasta Table Child Properties/XPadding
.
9.3 Ohjelman sulkeminen
"Poistu"-valikohkohta ei vielä toimi. Asetetaan sen tapahtumakäsittelijään ohjelman sulkeminen.
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.