[C#] Operatorul ?? nu acceptă variabile de tipuri diferite de o parte și de alta a sa.

Poate ați întâlnit mesajul acesta de eroare: „Operator '??' cannot be applied to operands of type 'int?' and 'DBNull'”.
    int? x = 8; // nullable type prin ?
    // Acest parametru SQL poate fi si NULL in baza de date, dar trimitand null la AddWithValue sterge parametrul, deci folosesc DBNull.Value.
    cmd.Parameters.AddWithValue("@x",
        x ?? DBNull.Value); // Da eroare de sintaxa.

    object y = x ?? DBNull.Value; // La fel si aici.

Fiindcă expresiile „null coalesce” (cele cu ??) nu pot avea tipuri diferite in stanga lui ?? si in dreapta lui ??, folosim o clauza if:

    if (x.HasValue) // conditie echivalenta cu (x != null)
    { 
        cmd.Parameters.AddWithValue("@x", x); 
    } 
    else 
    { 
        cmd.Parameters.AddWithValue("@x", DBNull.Value); 
    } 

Capturi de ecran:



Inspirație de aici.

[Visual Studio, C#] Folosirea unei baze de date SQL LocalDB în VS

Un astfel de bază de date locală se poate crea pe platforma SQL Server Express (2016) LocalDB în cazul ultimei versiuni de Visual Studio (Community 2017) care se instalează cu programul descărcat de pe site-ul Visual Studio, program numit Visual Studio Installer. Se urmează pașii de instalare (selectându-se desigur workload-ul .NET desktop development - dezvoltare desktop cu .NET) dar în secțiunea Individual components se bifează și SQL Server Express 2016 LocalDB și Data sources for SQL Server support.




După (re)pornirea VS și crearea noului proiect, sau deschiderea proiectului existent, se deschide panoul SQL Server Object Explorer în Visual Studio.


În captura de ecran următoare se vede locul de unde se poate copia șirul de caractere de conectare la baza de date:


Aici se vede cum se poate crea o nouă bază de date:


Aici se vede ce apare în panou după crearea bazei de date:


Aici se vede cum se creează un nou tabel în BD (Baza de Date):


În imaginea următoare se vede cum am modificat structura inițială a tabelului:


La apăsarea butonului Update (Actualizează), apare următoarea fereastră.


Din fereastra aceasta se apasă butonul Update Database. Apoi dispare fereastra aceasta, și apare un panou în partea de jos a ferestrei Visual Studio principale cu confirmarea succesului operațiunii:


Se alege din meniul contextual al tabelului elementul „View Data” (Vezi datele) pentru a vedea și în cazul nostru a actualiza datele din tabel:


Inițial nu există date în noul tabel:


Se introduc 2 rânduri în tabel (se salvează automat la tasta Enter sau clic în afara noului rând completat):


Se face clic dreapta pe elementul DesktopApp1 din panoul din dreapta Solution Explorer, apoi se alege opțiunea din noul meniu apărut numită Properties.


În pagina de nou deschisă, cea de proprietăți ale proiectului, se alege secțiunea Settings și se creează o setare la nivel de aplicație, deci o setare doar cu permisiune de citire pentru programul nostru, conținând șirul de caractere de conectare la baza de date arătat într-o captură de mai sus a Visual Studio. Acesta e deseori criptat pentru protejarea bazei de date.


În designer-ul unicului formular al proiectului adăugăm în formular un DataGridView (vedere de tabel cu date) în care vom afișa datele din tabelul SQL creat mai sus.


O parte din codul pentru afișare e în captura de mai jos:


În captura următoare vedem că am pus următorul rând la începutul fișierului (rândul 2) necesar pentru accesarea bazei de date:

    using System.Windows.Forms;



În următoarea captură de ecran am adăugat coloanele, fără de care nu pot exista rânduri în DataGridView:



Acum programul poate fi rulat și se afișează Form1 cu datele din tabel:

[C#] Traducerea valorilor booleane în lb. română

În lista de mai jos sunt reținute valori posibile pentru afișarea lui 0 sau 1 (true sau false), cu litere mici, deoarece urmează transformarea valorii introduse de utilizator în șir de caractere cu litere mici:

    List<string> valoriPosibile = new List<string>()
    {
        "0", "fals", "nu", "false", "off", "oprit",
        "1", "adevarat", "da", "true", "on", "pornit"
    };
    valoare = valoare.Trim().ToLower();

[C# WinForms] Gruparea Controalelor folosind proprietatea Tag și numere float

Pentru a calcula partea fractionara a unui numar de tip float in C#, se poate folosi, de exemplu, expresia:

x - (int)x

unde
- x este numele unei variabile de tip float;
- - este minus, operator matematic;
- (int) înseamnă că (int)x este partea întreagă a lui x;

De exemplu:

x - (int)x == 0.5F

unde

== este operatorul de verificare a egalității dintre 2 expresii;
0.5F este o expresie literală de tip float (F vine de la float) și „.” este separatorul dintre partea întreagă și cea fracțională a numărului (în lb. română acesta este , dar în C# se folosește .).


Exemplul #1

Cod sursă

float x = 1.5F;
float y = x - (int)x;
MessageBox.Show($"Partea fractionara a" +

    $" lui {x} este {y}.");

Captură de ecran


La rularea programului:

Exemplul #2

În urm. exemplu avem un container de Controale (UserControl, Form, Panel etc.) care conține mai multe Controale. Fiecare Control are o proprietate numită Tag care poate conține orice tip de obiect (string, float, tipuri valoare - struct, tipuri referință - class). În acest ex. atribuim proprietății Tag a tuturor Controalelor dintr-un container câte un nr. float, apoi traversăm colecția de controale Controls (sau this.Controls) și la fiecare verificăm valoarea Tag-ului: dacă partea fracționară este 0F sau 0.5F, astfel Controalele se pot grupa în mod eficient.

De exemplu:

            float tag = 1.5F; // Tag-ul transcris în tip float din designer WinForms sau din locul unde se construiește interfața grafică pentru utilizator, programatic.
            Control c = Controls[(int)tag]; // Controlul cu indicele ca partea întreagă a „tag”, variabilă care poate avea partea fracționară 0F sau 0.5F în acest exemplu, este gasit sau apare o excepție. (Controls nu se acceseaza decat prin indici numere naturale.)
            float x = tag - (int)tag; // partea fractionara a tag-ului
            if (x == 0.5F)
            {
                // ....
            }
            else if (x == 0F)
            {
                // ...
            }

Partea fractionara poate fi si 0.2F, 0.4F etc... Care valori sunt folosite depinde de caz.

Cod sursă complet (explicație dedesubt)

using System;
using System.Drawing;
using System.Windows.Forms;

namespace cs_winforms_tag_test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 5; i += 2)
            {
                Controls.Add(new TextBox()
                {
                    Tag = (float)i,
                    Left = 10,
                    Top = 10 + i * 20,
                    Text = "Din primul set"
                });
                Controls.Add(new TextBox()
                {
                    Tag = (float)i + 0.5F,
                    Left = 10,
                    Top = 10 + (i + 1) * 20,
                    Text = "Din al doilea set"
                });
            }

            Button btn = new Button()
            {
                Text = "Colorează",
                AutoSize = true,
                Left = 150,
                Top = 10
            };
            btn.Click += Btn_Click;
            Controls.Add(btn);
        }

        private void Btn_Click(object sender, EventArgs e)
        {
            foreach (Control c in Controls)
            {
                if (c.Tag == null)
                {
                    continue;
                }

                float tag = (float)(c.Tag);
                float pFractionara = tag - (int)tag;
                if (pFractionara == 0.5F)
                {
                    c.ForeColor = Color.Blue;
                }
                else
                {
                    c.ForeColor = Color.Green;
                }
            }
        }
    }
}

Explicație

Form1_Load este handler conectat la eventul Form1.Load, Form1 fiind singurul Form din proiect. In acest handler, i trece de la 0 la 4 in pasi de lungime 2, la fiecare pas creand 2 TextBox-uri cu valoarea Tag ca un numar float cu partea fractionara fie 0, fie 0.5. Se seteaza coordonatele vizuale ale TextBox-urilor, Left si Top. Fiecare TextBox are ca Text fie "Din primul set", fie "Din al doilea set". Se creeaza in acest handler si un buton pe care cand se face clic se coloreaza textul din TextBox-uri in functie de valoarea proprietatii lor Tag.

Capturi de ecran





La rularea programului:


După clic pe butonul Colorează:

Undo și Redo, pentru programatori

Ce are loc când utilizatorul programului tău execută comanda Undo:


Ce are loc când utilizatorul programului tău execută comanda Redo:


Când se adaugă un element în stiva Undo prin acțiunea utilizatorului au loc următorii pași:


P.S. La fiecare modificare a conținutul vreunei stive se actualizează starea de activat sau dezactivat a butoanelor Undo și Redo din interfața grafică.

[C# WinForms] Trasarea unei borduri unui PictureBox fără crearea unui UserControl

Pentru a trasa o bordură albastră unui PictureBox, înregistrez un handler la evenimentul Paint al PictureBox ca acesta:

private void Pb_Paint(object sender, PaintEventArgs e)
{
    ControlPaint.DrawBorder(e.Graphics,
        ((PictureBox)sender).DisplayRectangle,
        Color.Blue, ButtonBorderStyle.Solid);
}


Notă: la începutul fișierului .cs trebuie adăugat rândul acesta:

using System.Drawing;

Visual Studio poate adăuga acest rând automat.



Sursă inițială: https://stackoverflow.com/a/37513503/258462.

Capturi de ecran: