Fließkommazahl kulturunabhängig in einen String wandeln

Speichert man Fließkommazahlen auf unterschiedlichen Systemen als String ab, kommt es vor, dass diese kulturabhängig formatiert werden. Beim Parsen solcher Strings treten dann Fehler auf, weil das System z.B. nicht mit dem Decimalseparator klarkommt.

Das Problem kann man umgehen, indem man die Strings mittels CultureInfo.InvariantCulture umwandelt:

double v = 3.14;

string value = v.ToString(CultureInfo.InvariantCulture); // value == "3.14"

Das Einlesen muss dann ebenfalls über CultureInfo.InvariantCulture erfolgen:

string value = "3.14";
double dValue = 0.0;
if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out dValue))
{
    ...
}

Universeller Eingabedialog, ähnlich Borland Delphi InputQuery

  • Anwendungsbeispiele
// einfacher string input
string currentvalue = "test";

InputQuery iq = new InputQuery();
if (iq.ShowDlg("Please type something", "Value:", ref currentvalue, false, 32))
{
    string newval = currentvalue;
}

// einfacher floating point input
string currentvalue = "3.14";

InputQuery iq = new InputQuery();
if (iq.ShowDlg("Please type something", "Value:", ref currentvalue, true, -1))
{
    double newval = double.Parse(currentvalue);
}
  • Quellcode des Dialoges:
// Objekte und deren Eigenschaften, die sich auf dem Formular befinden müssen:
//
// lblValue - ein Label, welches vor der TextBox als Bezeichner steht
// tbValue - eine TextBox zur Eingabe
// tbValue.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.tbValue_KeyPress);
// btnOk - OK-Button
// btnOk.DialogResult = System.Windows.Forms.DialogResult.OK;
// btnCancel - Abbrechen-Button
// btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
// this.AcceptButton = this.btnOk;
// this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
// this.Name = "InputQuery";

using System.Globalization;
using System.Windows.Forms;

/// <summary->
/// freeware helper class for recreating Borland Deplhi InputQuery-Dialog
/// (W) 2011 by admin of codezentrale.6x.to
/// </summary->
public partial class InputQuery : Form
{
    private const int MAX_TEXTBOX_STR_LENGTH = 32767;
    private string ALLOWED_FP_INPUT_CHARS = "0123456789" + NumberFormatInfo.CurrentInfo.NumberDecimalSeparator + "\b";
    private bool _checkdouble = false;

    public InputQuery()
    {
        InitializeComponent();
    }
    /// <summary->
    /// Shows a little input-dialog
    /// </summary->
    /// <param name="dlgcaption"->dialog caption</param->
    /// <param name="lbl"->label text</param->
    /// <param name="value"->input value</param->
    /// <param name="checkdouble"->if input is a floating-point, check for correct format and decimalseparator</param->
    /// <param name="maxstringlength"->if input is a regular string, set maxlenght here, otherwise "-1"</param->
    /// <returns->true if button 'Ok' is pressed</returns->
    public bool ShowDlg(string dlgcaption, string lbl, ref string value, bool checkdouble, int maxstringlength)
    {
        lblValue.Text = lbl;
        this.Text = dlgcaption;
        tbValue.Text = value;
        _checkdouble = checkdouble;
        tbValue.MaxLength = checkdouble ? MAX_TEXTBOX_STR_LENGTH : maxstringlength -> 0 ? maxstringlength : MAX_TEXTBOX_STR_LENGTH;
        tbValue.SelectAll();
        DialogResult blOk = this.ShowDialog();
        value = tbValue.Text;
        return (blOk == DialogResult.OK);
    }

    private void tbValue_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == (char)(int)Keys.Enter)
        {
            this.DialogResult = DialogResult.OK;
        }
        else
            if (_checkdouble)
            {
                if (sender is TextBox)
                {
                    bool bNoDS = true;
                    TextBox tb = sender as TextBox;

                    if (e.KeyChar.ToString() == NumberFormatInfo.CurrentInfo.NumberDecimalSeparator)
                    {
                        bNoDS = (tb.Text.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator) < 0);
                    }

                    if (bNoDS)
                    {
                        e.Handled = (ALLOWED_FP_INPUT_CHARS.IndexOf(e.KeyChar) < 0);
                    }
                    else
                    {
                        e.Handled = true;
                    }
                }
            }
    }
}

Eigene Textformatierungen und Bitmaps im ListView darstellen (OwnerDraw)

ListView1.OwnerDraw = true;
ListView1.View = View.Details;

// ListView-Überschriften zeichnen
private void ListView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
    e.DrawBackground();

    StringFormat sf = new StringFormat();
    sf.Alignment = StringAlignment.Center;

    // da StringAlignment.Center, muss die Breite für die Darstellung durch 2 geteilt werden
    int iWidth = ListView1.Columns[e.ColumnIndex].Width / 2;
    
    // Header-String zentriert, schwarz und fett zeichnen
    e.Graphics.DrawString(e.Header.Text, new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold), Brushes.Black, e.Bounds.X + iWidth, e.Bounds.Y, sf);
}

// ListView-Subitems zeichnen
private void ListView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    StringFormat sf = new StringFormat();
    sf.Alignment = StringAlignment.Center;

    switch (e.ColumnIndex)
    {
        case 0:
            // Subitem 0 beinhaltet ein Bitmap
            Bitmap b = new Bitmap(@"c:\temp\test.jpg");
            e.Graphics.DrawImage(b, e.Bounds.X, e.Bounds.Y);
            break;
        default:
            // für alle anderen SubItems
            // halbe Spaltenbreite der akt. Spalte ausrechnen
            int iWidth = ListView1.Columns[e.ColumnIndex].Width / 2;
            // halbe Zellenhöhe ausrechnen
            int iHeight = (int)(ListView1.Font.SizeInPoints / 2.0);
            // String mit akt. Subitem-Text zeichnen
            e.Graphics.DrawString(e.SubItem.Text, new Font("Microsoft Sans Serif", 8.25F, FontStyle.Regular), Brushes.Black, e.Bounds.X + iWidth, e.Bounds.Y + iHeight, sf);
            break;
    }
}

// ListView-Item Hintergrund speziell färben, wenn focusiert
private void ListView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    if (e.State == ListViewItemStates.Focused)
    {
        e.Graphics.FillRectangle(Brushes.Beige, e.Bounds);
        e.DrawFocusRectangle();
    }
}

Drag und Drop innerhalb eines TreeViews

  • im Beispiel wird eine TreeNode innerhalb des TreeViews verschoben
  • als erstes ist das Ereignis ItemDrag zu behandeln:
private void TreeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
    TreeView tv = sender as TreeView;

    if (tv != null)
    {
        if (tv.SelectedNode != null)
        {
            tv.DoDragDrop(tv.SelectedNode, DragDropEffects.Copy);
        }
    }
}
  • beim TreeView muss die Eigenschaft AllowDrop = True gesetzt sein
  • zusätzlich sind die Ereignisse DragOver und DragDrop zu behandeln:
private void TreeView1_DragOver(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.None;

    // Quellnode
    TreeNode tns = e.Data.GetData(typeof(TreeNode)) as TreeNode;
    // akt. Zielnode unter dem Mauspfeil
    TreeNode tnd = TreeView1.GetNodeAt(TreeView1.PointToClient(new Point(e.X, e.Y)));

    if ((tns != null) && (tnd != null))
    {
        // hier im Beispiel die Verschiebung nur zulassen, wenn ChildNodes (Level == 1)
        // auf andere Parent-/Rootnodes (Level == 0) gezogen werden.
        if ((TreeView1.SelectedNode.Level == 1) && (tnd.Level == 0) && (tnd != tns.Parent))
        {
            e.Effect = DragDropEffects.Copy;
        }
    }
}

private void TreeView1_DragDrop(object sender, DragEventArgs e)
{
    // Quellnode
    TreeNode tns = e.Data.GetData(typeof(TreeNode)) as TreeNode;
    // akt. Zielnode unter dem Mauspfeil
    TreeNode tnd = TreeView1.GetNodeAt(TreeView1.PointToClient(new Point(e.X, e.Y)));

    if ((tns != null) && (tnd != null))
    {
        // neue TreeNode aus Clone der Quellnode erstellen
        TreeNode tnnew = (TreeNode)tns.Clone();
        tnd.Nodes.Add(tnnew);
        tnd.Expand();

        // alte Quell-TreeNode entfernen
        TreeNode cat = tns.Parent;
        cat.Nodes.Remove(tns);
    }
}

[C#][OleDB] Daten aus MSAccess in einem DataGridView darstellen

string sOleConnStr = string.Empty;
string sMDBFile = @"c:\Test.mdb";
string sUser = "user";
string sPassword = "password";
string sSQL = "SELECT * FROM table";

if (sMDBFile.Contains(".mdb"))
{
    sOleConnStr = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + sMDBFile + ";User ID=" + sUser + ";Jet OLEDB:Database Password=" + sPassword;
}
else
    if (sMDBFile.Contains(".accdb"))
    {
        sOleConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + sMDBFile + ";User ID=" + sUser + ";Jet OLEDB:Database Password=" + sPassword;
    }

if (string.IsNullOrEmpty(sOleConnStr))
{
    MessageBox.Show("Sie haben eine nicht unterstützte MS Access Datenbankdatei ausgewählt.", AssemblyInfo.AssemblyProduct, MessageBoxButtons.OK, MessageBoxIcon.Warning);
    return;
}

OleDbConnection olecon = null;
OleDbDataReader olereader = null;

try
{
    olecon = new OleDbConnection(sOleConnStr);
    olecon.Open();

    OleDbCommand cmd = new OleDbCommand(sSQL, olecon);
    olereader = cmd.ExecuteReader();

    BindingSource bSource = new BindingSource();
    bSource.DataSource = olereader;

    // Datagridview auf einem Formular zum anzeigen der Daten
    dgvData.DataSource = bSource;
}
catch (Exception eole)
{
    MessageBox.Show(eole.Message, AssemblyInfo.AssemblyProduct, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
    // aufräumen
    if (olereader != null) olereader.Close();
    if (olecon != null) olecon.Close();
}

[OleDB] Tabellen einer MSAccess Datenbank auslesen

string sOleConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Test.accdb;User ID=;Jet OLEDB:Database Password=";

OleDbConnection olecon = new OleDbConnection(sOleConnStr);
olecon.Open();

DataTable dbSchemaTable = olecon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });

foreach (DataRow row in dbSchemaTable.Rows)
{
    Console.WriteLine(row["TABLE_NAME"].ToString());
}

[C#] Farbmodelle umwandeln (HSV, RGB)

using System;
using System.Drawing;

/// <summary>
/// freeware helper class for converting color schemes
/// (W) 2011 by admin of codezentrale.6x.to
/// </summary>
public static class ColorConvert
{
    public struct HSV
    {
        /// <summary>
        /// Hue, Farbton [0.0° .. 360.0°]
        /// </summary>
        public double hue;
        /// <summary>
        /// Saturation, Sättigung [0.0 .. 1.0]
        /// </summary>
        public double saturation;
        /// <summary>
        /// Value, Helligkeit [0.0 .. 1.0]
        /// </summary>
        public double value;

        public HSV(double h, double s, double v)
        {
            hue = h;
            saturation = s;
            value = v;
        }
    }
    public struct RGB
    {
        /// <summary>
        /// red, Rot [0 .. 255]
        /// </summary>
        public int red;
        /// <summary>
        /// green, Grün [0 .. 255]
        /// </summary>
        public int green;
        /// <summary>
        /// blue, Blau [0 .. 255]
        /// </summary>
        public int blue;

        public RGB(int r, int g, int b)
        {
            red = r;
            green = g;
            blue = b;
        }
    }
    /// <summary>
    /// converts Color to HSV
    /// </summary>
    /// <param name="c">Color</param>
    /// <returns>HSV struct</returns>
    public static HSV ColorToHSV(Color c)
    {
        int max = Math.Max(c.R, Math.Max(c.G, c.B));
        int min = Math.Min(c.R, Math.Min(c.G, c.B));

        double h = c.GetHue();
        double s = (max == 0) ? 0.0 : 1.0 - (1.0 * (double)min / (double)max);
        double v = (double)max / 255.0;

        return new HSV(h, s, v);
    }
    /// <summary>
    /// converts HSV to Color
    /// </summary>
    /// <param name="hsv">HSV struct to convert</param>
    /// <returns>Color</returns>
    public static Color HSVToColor(HSV hsv)
    {
        Color c = Color.Black;

        int hi = (int)(Math.Floor(hsv.hue / 60.0)) % 6;
        double f = hsv.hue / 60.0 - Math.Floor(hsv.hue / 60.0);

        hsv.value = hsv.value * 255.0;

        int v = (int)hsv.value;
        int p = (int)(hsv.value * (1.0 - hsv.saturation));
        int q = (int)(hsv.value * (1.0 - f * hsv.saturation));
        int t = (int)(hsv.value * (1.0 - (1.0 - f) * hsv.saturation));

        switch (hi)
        {
            case 0: c = Color.FromArgb(255, v, t, p); break;
            case 1: c = Color.FromArgb(255, q, v, p); break;
            case 2: c = Color.FromArgb(255, p, v, t); break;
            case 3: c = Color.FromArgb(255, p, q, v); break;
            case 4: c = Color.FromArgb(255, t, p, v); break;
            default: c = Color.FromArgb(255, v, p, q); break;
        }

        return c;
    }
    /// <summary>
    /// converts Color to RGB
    /// </summary>
    /// <param name="c">Color</param>
    /// <returns>RGB struct</returns>
    public static RGB ColorToRGB(Color c)
    {
        return new RGB(c.R, c.G, c.B);
    }
    /// <summary>
    /// converts RGB to Color
    /// </summary>
    /// <param name="rgb">RGB struct</param>
    /// <returns>Color</returns>
    public static Color RGBToColor(RGB rgb)
    {
        return Color.FromArgb(rgb.red, rgb.green, rgb.blue);
    }
}