Grafikus C# – Windows Forms tanfolyam › 10.8 lecke Windows Forms · 10.8 lecke · beállítások Egy jó program emlékszik: ugyanabban a helyen és méretben nyílik meg, ahol bezártad, megőrzi a témát, a betűméretet és az utolsó mappát. Az ilyen apró, a programhoz és a felhasználóhoz tartozó értékek tárolására a .NET beépített megoldása az Application Settings (Application Settings
Properties.Settings): a Visual Studio szerkesztőjében felveszed a beállításokat, a kódban típusos tulajdonságként éred el, a mentést és az XML-fájl helyét a keretrendszer intézi. Ebben a leckében megtanulod a használatát (Save, Reset, Upgrade), az ablakpozíció helyes mentését (több monitor, kis ablak), a legutóbbi fájlok tárolását, a sérült beállításfájl kezelését, és tudni fogod, mikor nem ez a jó megoldás.
A lecke végére
- felveszel beállítást a Settings szerkesztőben (név, típus, hatókör, alapérték), és típusosan éred el;
- megkülönbözteted a felhasználói és az alkalmazás hatókört (csak a felhasználói írható);
- mentesz, visszaállítasz és frissítesz (
Save,Reload,Reset,Upgrade); - az ablak helyét és méretét helyesen tárolod (
RestoreBounds, képernyőn kívüli pozíció kezelése); - listát (
StringCollection) és színt tárolsz; - kezeled a sérült beállításfájlt, és tudod, mi tartozik a beállításokba, és mi nem (jelszó, nagy adat).
Mielőtt elkezded
Ehhez a leckéhez az 5.6 lecke (a Form életciklusa: Load, FormClosing), a 10.1 lecke (adatmappák) és a 10.6 lecke (JSON, a beállítások alternatívájaként) szükséges. A Settings szerkesztő a Visual Studio Solution Explorer → Properties → Settings.settings fájljában érhető el.
Beállítások felvétele és elérése
A Settings.settings szerkesztőben táblázatban adod meg a beállításokat: Name (név), Type (típus: string, int, bool, System.Drawing.Color, Size, Point, StringCollection…), Scope (hatókör) és Value (alapérték). A Visual Studio a Properties.Settings.Default osztályba típusos tulajdonságokat generál:
| Name | Type | Scope | Value (alapérték) |
|---|---|---|---|
HatterSzin | System.Drawing.Color | User | White |
BetuMeret | int | User | 11 |
AblakHely | System.Drawing.Point | User | 0, 0 |
AblakMeret | System.Drawing.Size | User | 800, 600 |
AblakAllapot | string | User | Normal |
Legutobbi | System.Collections.Specialized.StringCollection | User | (üres) |
IndulasokSzama | int | User | 0 |
FrissitesKell | bool | User | True |
Szerver | string | Application | https://pelda.hu (csak olvasható) |
// olvasás: típusos tulajdonságok, nincs konverzió
int meret = Properties.Settings.Default.BetuMeret;
Color hatter = Properties.Settings.Default.HatterSzin;
// írás (csak a User hatókörű): a memóriában azonnal érvényes, a lemezre a Save írja
Properties.Settings.Default.BetuMeret = 14;
Properties.Settings.Default.Save();
// az alkalmazás-hatókörű érték csak olvasható: az írási kísérlet nem fordul le
string szerver = Properties.Settings.Default.Szerver;user.config fájlba kerül a felhasználó %LocalAppData% mappájában. Ide valók a személyes beállítások (téma, ablakméret, utolsó mappa).*.exe.config) tárolódik. Szerver cím, alapértelmezett limit: olyan érték, amelyet a telepítő vagy az üzemeltető módosít.int.Parse. A Color, Size, Point, Font is használható (a program XML-szövegként tárolja).Save() hívására. Hívás nélkül a módosítás a program leállásával elvész. Ezért a FormClosing vagy az érték módosítása után kell mentened.Jósolj!
A program Properties.Settings.Default.BetuMeret = 14; értéket állít be, de a Save() hívás kimarad. A felhasználó bezárja és újra megnyitja a programot. Mekkora a betűméret?
Jóslat ellenőrzése
11 (az utoljára mentett vagy az alapérték): a módosítás csak a memóriában élt, és a program bezárásakor elveszett. A Save() nélkül nincs tartós változás.
Mentés, Reload, Reset és Upgrade
private void Form1_Load(object sender, EventArgs e)
{
Properties.Settings be = Properties.Settings.Default;
// a program új verziója új user.config mappát kap: az előző verzió beállításait át kell hozni
if (be.FrissitesKell)
{
be.Upgrade(); // az előző verzió értékeit betölti
be.FrissitesKell = false; // az új verzió fájljában már hamis
be.Save();
}
be.IndulasokSzama++;
if (be.Legutobbi == null) { be.Legutobbi = new StringCollection(); } // a gyűjtemény alapból null lehet
this.BackColor = be.HatterSzin;
this.Font = new Font(this.Font.FontFamily, be.BetuMeret);
}
private void btnAlaphelyzet_Click(object sender, EventArgs e)
{
if (MessageBox.Show(this, "Visszaállítod a beállításokat az alapértékekre?", "Beállítások", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
{
Properties.Settings.Default.Reset(); // minden User érték az alapérték (a Save-ig csak a memóriában)
Properties.Settings.Default.Save();
}
}
// a módosítás elvetése: a legutóbb mentett állapot visszatöltése
Properties.Settings.Default.Reload();Reset() a felhasználói beállításokat az alapértékekre állítja. A fájlt a Save() írja; mentés nélkül csak a memóriában változik.Reload() a lemezről újratölti a mentett értékeket (a nem mentett módosítást elveti): „Mégse” gombhoz ideális.FrissitesKell jelző mintája: az első indításnál Upgrade() átveszi az előző verzió értékeit, majd a jelzőt hamisra állítja és menti.StringCollection alapértéke üres beállításnál null lehet. Használat előtt ellenőrizd és hozd létre. A gyűjtemény elemeinek módosítása után is hívj Save() metódust.Jósolj!
A program új változata (1.1) kijön, a felhasználó telepíti. A programban nincs Upgrade() hívás. Mit tapasztal a felhasználó?
Jóslat ellenőrzése
Hogy a program elfelejtett mindent: az új verzió új beállítás-mappát használ, és üres (alapértékű) beállításokkal indul. Az Upgrade() az előző verzió user.config fájljából hozza át az értékeket.
Az ablak helyének és méretének tárolása
// visszaállítás indításkor
private void AblakVisszaallit()
{
Properties.Settings be = Properties.Settings.Default;
Size meret = be.AblakMeret;
Point hely = be.AblakHely;
// ellenőrzés: elég nagy-e a méret, és az ablak látszik-e valamelyik (még meglévő) képernyőn?
if (meret.Width < this.MinimumSize.Width || meret.Height < this.MinimumSize.Height) { return; } // érvénytelen, marad az alap
Rectangle kert = new Rectangle(hely, meret);
bool latszik = Screen.AllScreens.Any(s => s.WorkingArea.IntersectsWith(kert) && Rectangle.Intersect(s.WorkingArea, kert).Width >= 100);
if (!latszik) { return; } // a monitor megszűnt (kihúzott kijelző): a program az alapértelmezett helyen nyílik
this.StartPosition = FormStartPosition.Manual;
this.Location = hely;
this.Size = meret;
if (be.AblakAllapot == "Maximized") { this.WindowState = FormWindowState.Maximized; }
}
// mentés bezáráskor
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings be = Properties.Settings.Default;
if (this.WindowState == FormWindowState.Normal)
{
be.AblakHely = this.Location;
be.AblakMeret = this.Size;
be.AblakAllapot = "Normal";
}
else
{
be.AblakHely = this.RestoreBounds.Location; // a maximalizált/kis méretű ablaknál a visszaállítandó méret
be.AblakMeret = this.RestoreBounds.Size;
be.AblakAllapot = this.WindowState == FormWindowState.Maximized ? "Maximized" : "Normal"; // minimalizálva nem indítunk
}
try { be.Save(); }
catch (System.Configuration.ConfigurationErrorsException) { } // a beállítás mentése nem akadályozhatja a kilépést
}Location és Size az ideiglenes értéket (teljes képernyő, a tálca melletti pont) adja. A RestoreBounds a normál állapot helyét és méretét: ezt kell menteni.Screen.AllScreens alapján ellenőrizd, hogy az ablak legalább egy része (itt 100 képpont szélesen) látszik.FormClosing (vagy FormClosed) eseményben történik (5.6 lecke). A mentés hibája nem akadályozhatja meg a kilépést.Jósolj!
A felhasználó a program ablakát maximalizálva zárja be. A FormClosing a this.Location és this.Size értéket menti. Legközelebb a program normál állapotban indul. Hol és mekkora lesz az ablak?
Jóslat ellenőrzése
Gyakran a teljes képernyő méretében (vagy a képernyő szélén, negatív koordinátával): a maximalizált ablak Location és Size értéke a képernyőhöz igazodik, nem az előző normál mérethez. A RestoreBounds a helyes.
Sérült beállításfájl és a Settings korlátai
// A sérült user.config az első Properties.Settings.Default eléréskor ConfigurationErrorsException kivételt dob.
// Ezért az első elérést védjük, és szükség esetén töröljük a hibás fájlt.
private static void BeallitasokEllenorzese()
{
try
{
int proba = Properties.Settings.Default.BetuMeret; // az első elérés tölti be a fájlt
}
catch (ConfigurationErrorsException ex)
{
string fajl = ex.Filename;
if (string.IsNullOrEmpty(fajl) && ex.InnerException is ConfigurationErrorsException) { fajl = ((ConfigurationErrorsException)ex.InnerException).Filename; }
DialogResult v = MessageBox.Show("A beállításfájl sérült, ezért nem tölthető be. Alaphelyzetbe állítsam a beállításokat?", "Beállítások", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (v == DialogResult.Yes && fajl != null && File.Exists(fajl))
{
File.Move(fajl, fajl + ".hibas"); // nem törlünk: a hibás fájl megmarad a vizsgálathoz
}
else { Environment.Exit(0); }
}
}
// Main elején: BeallitasokEllenorzese(); Application.Run(new Form1());| Adat | Application Settings? | Miért? |
|---|---|---|
| Téma, betűméret, ablakméret, utolsó mappa | Igen | Kicsi, felhasználónkénti, nem érzékeny. |
| Legutóbbi fájlok (néhány elem) | Igen | StringCollection, kicsi. |
| Jelszó, API-kulcs, token | NEM | Titkosítatlan XML-fájl: jelszót ne tárolj. Használj védett tárolót (Windows Credential Manager, ProtectedData). |
| A felhasználó dokumentumai, névjegyek, jegyzetek | NEM | Saját fájl (JSON, 10.6 lecke): megosztható, mentésbe vonható, nagyobb. |
| Hordozható program (pendrive-on) | NEM | A beállítások a gép felhasználói mappájában vannak: saját beallitasok.json a program mellett. |
| Több profil, több ablak | NEM | Egyetlen user.config: profilokhoz saját fájl. |
Jósolj!
A program a felhasználó e-mail-jelszavát egy User hatókörű Jelszo beállításban tárolja, hogy ne kelljen mindig beírni. Ki olvashatja el?
Jóslat ellenőrzése
Bárki, aki hozzáfér a felhasználó mappájához (más program, a gép másik használója rendszergazdaként, egy biztonsági mentés): a user.config szöveges XML, a jelszó olvasható benne. Jelszót nem tárolunk a beállításokban; ha feltétlenül kell, a Windows védett tárolóját használd.
Mit tegyél ide: a Settings szerkesztő a felvett beállításokkal, mellette a kész beállításkezelő program.Javasolt fájlnév: winforms-10-8-beallitasok.webp · Alt szöveg: A Settings szerkesztő és a beállításkezelő
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. A beállítás nem marad meg
Properties.Settings.Default.HatterSzin = Color.Gold; // nincs Save()Hiba és javítás
A Save() hívás hiányzik. Mentsd a módosítás után (vagy a FormClosing-ben).
2. A fordító hibát jelez az írásnál
Properties.Settings.Default.Szerver = "masik.hu"; // Application hatókörHiba és javítás
Az Application hatókörű érték csak olvasható. Ha a program módosítja, a hatókörnek Usernek kell lennie.
3. Új verzió után minden beállítás elveszett
A frissítés utáni induláskor a program alapértékekkel indul. Hiányzik az Ok és javítás
Upgrade(). Használd a FrissitesKell jelző mintáját az első indításnál.
4. NullReferenceException a Legutobbi gyűjteménynél
Properties.Settings.Default.Legutobbi.Add(ut); // az első indításkor nullHiba és javítás
A StringCollection alapból null lehet. Ellenőrizd és hozd létre: if (Legutobbi == null) Legutobbi = new StringCollection();.
5. Az ablak a képernyőn kívül nyílik meg
A második monitor eltávolítása után a program „eltűnik”. A mentett hely nincs ellenőrizve. Ellenőrizd a Ok és javítás
Screen.AllScreens alapján, hogy a hely látszik-e; ha nem, az alapértelmezett pozíciót használd.
6. A program összeomlik az indulásnál
Az indulásnál ConfigurationErrorsException jön. A Ok és javítás
user.config sérült (kézi szerkesztés, megszakadt mentés). Kezeld az első elérést, és ajánlj alaphelyzetet (a hibás fájl átnevezése).
Mini projekt: beállításkezelő
Készíts programot, amely emlékszik a felhasználó beállításaira:
- Settings: a lecke táblázata szerinti beállítások (
HatterSzin,BetuMeret,AblakHely,AblakMeret,AblakAllapot,Legutobbi,IndulasokSzama,FrissitesKell), kiegészítve:ElsoIndulas(bool, True),UtolsoMappa(string),Tema(string, Vilagos). - Felület:
txtSzoveg(próbaszöveg), beállító panel:cmbTema(Világos, Sötét, Magas kontraszt),btnHatter(Háttérszín...,ColorDialog),nudBetu(8–32),lblIndulas(Ez a(z) 17. indítás),lstLegutobbi; gombok: Alaphelyzet, Beállítások exportálása..., Importálás...; állapotsor: a beállítások helye (%LocalAppData%). - Indulás:
BeallitasokEllenorzese(sérült fájl kezelése),Upgradea jelzővel, az ablak visszaállítása (RestoreBounds, képernyő-ellenőrzés), a téma és a betűméret alkalmazása, az indítások számának növelése. - Első indítás: az
ElsoIndulasigaz esetén üdvözlő ablak (Köszöntelek!) rövid bemutatóval, utána a jelző hamis. - Élő előnézet: a beállítások módosítása azonnal látszik; a Mégse a
Reload(), az OK aSave()(egyAlkalmaz/Megsegombpár). - Érvényesítés betöltéskor: a
BetuMeret8–32 közé szorítva (Math.Max,Math.Min); ismeretlen téma esetén az alap; a háttérszín és a szövegszín kontrasztja ellenőrizve (a magas kontraszt téma kényszeríti). - Exportálás és importálás: a beállítások (a téma, a betűméret, a háttérszín) JSON-ba (10.6 lecke, a szín
#RRGGBBszövegként); importálásnál az értékek ellenőrzése, hibás fájl jelentése; így a beállítások átvihetők másik gépre. - Legutóbbi fájlok: a
StringCollection(legfeljebb 8, duplikátum nélkül, az új elöl); a Fájl megnyitása gomb az utolsó mappából indul (10.4 lecke). - Hibatűrés: a
Save()hibája (ConfigurationErrorsException,IOException,UnauthorizedAccessException) az állapotsorban jelenik meg, a program nem omlik össze. - Teszteld: első indítás, újraindítás (ablak helye, mérete, maximalizált állapot), a második monitor eltávolítása (ha van), alaphelyzet, a
user.configszándékos elrontása (egy < jel hozzáadása), nagy betűméret, a Mégse és az OK, export–import, 10 egymás utáni indítás (számláló).
Megoldás megnyitása (próbáld ki előbb önállóan!)
A központi rész az indulás sorrendje (ellenőrzés → upgrade → ablak → téma) és a mentés a bezáráskor.
private Properties.Settings be { get { return Properties.Settings.Default; } }
private void Form1_Load(object sender, EventArgs e)
{
if (be.FrissitesKell) { be.Upgrade(); be.FrissitesKell = false; be.Save(); }
if (be.Legutobbi == null) { be.Legutobbi = new StringCollection(); }
be.BetuMeret = Math.Max(8, Math.Min(32, be.BetuMeret)); // érvényesítés
cmbTema.Items.AddRange(new object[] { "Világos", "Sötét", "Magas kontraszt" });
cmbTema.SelectedItem = cmbTema.Items.Contains(be.Tema) ? be.Tema : "Világos";
AblakVisszaallit();
Alkalmaz();
be.IndulasokSzama++;
lblIndulas.Text = "Ez a(z) " + be.IndulasokSzama + ". indítás.";
foreach (string ut in be.Legutobbi) { lstLegutobbi.Items.Add(ut); }
if (be.ElsoIndulas)
{
MessageBox.Show(this, "Köszöntelek! A beállításaidat a program megjegyzi.", "Üdv", MessageBoxButtons.OK, MessageBoxIcon.Information);
be.ElsoIndulas = false;
}
tsslHely.Text = "Beállítások: %LocalAppData%";
}
private void Alkalmaz()
{
Color hatter = be.HatterSzin, szoveg = Color.Black;
switch (cmbTema.SelectedItem as string)
{
case "Sötét": hatter = Color.FromArgb(32, 32, 36); szoveg = Color.WhiteSmoke; break;
case "Magas kontraszt": hatter = Color.Black; szoveg = Color.Yellow; break; // a kontraszt kikényszerítve
}
txtSzoveg.BackColor = hatter;
txtSzoveg.ForeColor = szoveg;
// az új betű létrehozása, a régi felszabadítása a csere UTÁN
Font uj = new Font(txtSzoveg.Font.FontFamily, be.BetuMeret);
Font elozo = txtSzoveg.Font;
txtSzoveg.Font = uj;
elozo.Dispose(); // a TextBox a beállított betűt nem szabadítja fel (9.8 lecke)
}
private void AblakVisszaallit()
{
Size meret = be.AblakMeret;
Point hely = be.AblakHely;
if (meret.Width < this.MinimumSize.Width || meret.Height < this.MinimumSize.Height) { return; }
Rectangle kert = new Rectangle(hely, meret);
bool latszik = Screen.AllScreens.Any(s => Rectangle.Intersect(s.WorkingArea, kert).Width >= 100 && Rectangle.Intersect(s.WorkingArea, kert).Height >= 50);
if (!latszik) { return; }
this.StartPosition = FormStartPosition.Manual;
this.Location = hely;
this.Size = meret;
if (be.AblakAllapot == "Maximized") { this.WindowState = FormWindowState.Maximized; }
}
private void btnAlkalmaz_Click(object sender, EventArgs e)
{
be.Tema = (string)cmbTema.SelectedItem;
be.BetuMeret = (int)nudBetu.Value;
Alkalmaz();
Ment();
}
private void btnMegse_Click(object sender, EventArgs e)
{
be.Reload(); // a nem mentett módosítás elvetése
nudBetu.Value = be.BetuMeret;
Alkalmaz();
}
private void btnAlaphelyzet_Click(object sender, EventArgs e)
{
if (MessageBox.Show(this, "Visszaállítod az összes beállítást az alapértékre?", "Alaphelyzet", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != DialogResult.Yes) { return; }
be.Reset();
be.FrissitesKell = false;
be.ElsoIndulas = false;
nudBetu.Value = be.BetuMeret;
Alkalmaz();
Ment();
}
private void Ment()
{
try { be.Save(); tsslUzenet.Text = "A beállítások mentve."; }
catch (ConfigurationErrorsException ex) { tsslUzenet.Text = "A mentés nem sikerült: " + ex.Message; }
catch (IOException ex) { tsslUzenet.Text = "A mentés nem sikerült: " + ex.Message; }
catch (UnauthorizedAccessException) { tsslUzenet.Text = "Nincs jogosultság a beállítások mentéséhez."; }
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.WindowState == FormWindowState.Normal) { be.AblakHely = this.Location; be.AblakMeret = this.Size; be.AblakAllapot = "Normal"; }
else { be.AblakHely = this.RestoreBounds.Location; be.AblakMeret = this.RestoreBounds.Size; be.AblakAllapot = this.WindowState == FormWindowState.Maximized ? "Maximized" : "Normal"; }
Ment();
}
// export: csak a hordozható értékek, a szín #RRGGBB szövegként (10.6 lecke)
private void btnExport_Click(object sender, EventArgs e)
{
int idx;
string ut = FajlValaszto.Ment(this, "Beállítások (*.json)|*.json", be.UtolsoMappa, "beallitasok", out idx);
if (ut == null) { return; }
var adat = new { tema = be.Tema, betuMeret = be.BetuMeret, hatterSzin = ColorTranslator.ToHtml(be.HatterSzin) };
try { File.WriteAllText(ut, JsonSerializer.Serialize(adat, new JsonSerializerOptions { WriteIndented = true })); }
catch (IOException ex) { MessageBox.Show(this, ex.Message, "Exportálás", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}
private void btnImport_Click(object sender, EventArgs e)
{
string ut = FajlValaszto.Megnyit(this, "Beállítások (*.json)|*.json", be.UtolsoMappa);
if (ut == null) { return; }
try
{
using (JsonDocument dok = JsonDocument.Parse(File.ReadAllText(ut)))
{
JsonElement gy = dok.RootElement, v;
int meret;
if (gy.TryGetProperty("betuMeret", out v) && v.TryGetInt32(out meret) && meret >= 8 && meret <= 32) { be.BetuMeret = meret; }
if (gy.TryGetProperty("tema", out v) && cmbTema.Items.Contains(v.GetString())) { be.Tema = v.GetString(); }
if (gy.TryGetProperty("hatterSzin", out v)) { try { be.HatterSzin = ColorTranslator.FromHtml(v.GetString()); } catch (Exception) { } }
}
Alkalmaz();
Ment();
}
catch (JsonException ex) { MessageBox.Show(this, "Hibás beállításfájl: " + ex.Message, "Importálás", MessageBoxButtons.OK, MessageBoxIcon.Warning); }
catch (IOException ex) { MessageBox.Show(this, ex.Message, "Importálás", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}Mit tegyél ide: a kész beállításkezelő a témaválasztóval és az indítások számával.Javasolt fájlnév: winforms-10-8-kesz.webp · Alt szöveg: A kész beállításkezelő
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Utolsó splitter-pozíció
Egy Egy SplitContainer elválasztójának helyét tárold. Melyik beállítás típusát használod, és mikor állítod vissza?Egy lehetséges megoldás
int beállítás (SplitHely); a Load-ban a SplitterDistance beállítása érvényesítéssel (a Panel1MinSize és az ablakméret határain belül), a FormClosing-ben a mentés.
2. Indítás számláló és köszöntés
A program a 10., 50., 100. indításnál „kerek” indításra gratulál. Hol számolsz? A Egy lehetséges megoldás
Load-ban az IndulasokSzama++ után; az int beállítást ellenőrzöd (szam % 50 == 0 vagy tömb). Az indítás számát a Save menti, ezért a számláló megbízhatósága a menthetőségtől függ.
3. Beállítások két ablakban
A program két ablakot nyit meg (főablak és beállítóablak), mindkettő a Nem: a Settings.Default osztályt használja. Szükséges-e átadni a beállításokat?Egy lehetséges megoldás
Settings.Default egyetlen példány (singleton), mindenhol ugyanaz. A beállítóablak módosít és Save-et hív; a főablaknak értesítés kell (esemény vagy PropertyChanged), hogy újraalkalmazza az értékeket (7.6 lecke eseménye).
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Melyik hatókör?
Válaszd ki a hatókört: (a) a felhasználó témája; (b) a szerver címe, amelyet az üzemeltető állít be. (a) User (olvasható és írható); (b) Application (csak olvasható).Megoldás megnyitása
2. Mi hiányzik?
A felhasználó módosítja a témát, de újraindítás után a régi téma tér vissza. Mi a hiba? A Megoldás megnyitása
Save() hívás hiányzik (vagy a mentés kivételt dobott, amelyet elnyelt).
Közepes szint
3. Kontraszt-ellenőrzés
Hogyan ellenőrzöd, hogy a betöltött háttér- és szövegszín kontrasztja megfelelő? A relatív fényesség arányából (6.9 lecke): ha 4,5 alatt van, a program az alap színeket vagy a magas kontraszt témát alkalmazza.Megoldás megnyitása
4. Hordozható mód
A program a beállításait a saját mappájában lévő Ha a program mellett van beallitasok.json fájlba is mentheti (pendrive). Hogyan döntöd el, melyiket használod?Megoldás megnyitása
portable.txt jelzőfájl (és a mappa írható), akkor a JSON; különben a Settings. A beállítás-réteg egy közös felület mögött (IBeallitasok) lehet.
Kihívás szint
5. SettingsSaving esemény
Mentés előtt a program ellenőrzi az értékeket, és szükség esetén megakadályozza a mentést. Mit használsz? A Megoldás megnyitása
Properties.Settings.Default.SettingsSaving esemény (CancelEventArgs): az e.Cancel = true megállítja a mentést. Az ellenőrzés egy helyen van, bárhonnan hívják a Save() metódust.
6. Titkosított érték
Egy API-kulcsot mégis tárolni kell. Hogyan teszed biztonságosabbá? A Megoldás megnyitása
ProtectedData.Protect (DataProtectionScope.CurrentUser) a felhasználó Windows-fiókjához köti a titkosítást; a titkosított bájtokat Base64 szövegként tárolod. Jobb a Windows Credential Manager. Titkosított értéket sem naplózol, és nem írsz ki.
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A User felhasználónként külön és írható; az Application az egész programra érvényes és futás közben csak olvasható. A Az új verzió az előző verzió beállításait átveszi. Maximalizált vagy minimalizált ablaknál a A monitor megszűnhetett: az ablak a képernyőn kívül „eltűnne”. Jelszót és más érzékeny adatot, a felhasználó dokumentumait és nagy adatot. Kezeled a 1. Mi a különbség a User és az Application hatókör között?
2. Mikor kerül lemezre a beállítás?
Save() hívásra.3. Mire való az Upgrade?
4. Miért a RestoreBounds-t mentjük?
Location/Size félrevezető; a RestoreBounds a normál állapot.5. Miért ellenőrizzük az ablak helyét indításkor?
6. Mit ne tárolj a Settings-ben?
7. Mit teszel sérült user.config esetén?
ConfigurationErrorsException kivételt, a fájlt átnevezed (nem törlöd), és alaphelyzetben indulsz.
Mit tudsz már?
- Beállításokat veszel fel és használsz típusosan, a hatókör ismeretében.
- Mentesz, visszaállítasz és frissítesz (
Save,Reload,Reset,Upgrade). - Az ablak helyét és méretét helyesen, több monitor mellett is kezeled.
- Kezeled a sérült beállításfájlt.
- Tudod, mi való a
Settingsosztályba, és mi nem.
Következő lecke: mentési hibák, fájlzárak és kivételkezelés
Megbízható mentés: ideiglenes fájl és csere, biztonsági másolat, újrapróbálkozás zárolt fájlnál, a tipikus IOException okok és az érthető hibaüzenetek.



