Benutzer mit den meisten Antworten
In gebundener Textbox (DateTime) nur den Teil des Datums anzeigen

Frage
-
Hallo,
ich habe in der SQL Datenbank 2 DateTime Felder in welche in Von- und Bis-Datum und Zeit eingetragen werden kann.
Die Eingabe soll auf 3 Controls (1 x Datum und 2 x Zeit) aufgeteilt werden. Das Datum brauche ich nur einmal weil es für diese Abteilung keine tagesübergreifenden Tätigkeiten gibt.
Mein Problem ist, dass ich es nicht schaffe in der Datumstextbox nur das Datum anzeigen zu lassen. Die TextBox ist gebunden. Es wird immer Datum und Zeit angezeigt. Ein DateTimePicker Control kann ich nicht nehmen, weil es gut mit der Tastatur einzugeben sein soll.
Eine Formattierungsmöglichkeit in der Textbox habe ich nciht gefunden.
Hat jemand eine Idee?
Vielen Dank
Siegfried
Antworten
-
Hi Siegfried,
nachfolgend eine kleine Demo am Beispiel einer Bindung mit einer DataTable:using System; using System.Data; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form02 : Form { public Form02() { InitializeComponent(); } TextBox tb1 = new TextBox() { Dock = DockStyle.Top }; TextBox tb2 = new TextBox() { Dock = DockStyle.Top }; TextBox tb3 = new TextBox() { Dock = DockStyle.Top }; DataGridView dgv = new DataGridView() { Dock = DockStyle.Fill }; private void Form02_Load(object sender, EventArgs e) { this.Controls.AddRange(new Control[] { dgv, tb3, tb2, tb1 }); DatenBinden(); } DataTable tab = new DataTable(); BindingSource bs = new BindingSource(); private void DatenBinden() { Random rnd = new Random(); // Tabelle tab.Columns.Add("von", typeof(DateTime)); tab.Columns.Add("bis", typeof(DateTime)); for (int i = 0; i < 10; i++) { tab.Rows.Add(DateTime.Now.AddMinutes(rnd.Next(1000)), DateTime.Now.AddMinutes(rnd.Next(2000))); } // BindingSource füllen bs.DataSource = tab; // Grid binden dgv.DataSource = bs; // von-Datums-Box Binding b1 = new Binding("Text", bs, "von"); b1.Format += Datum_Format; b1.Parse += Datum_Parse; tb1.DataBindings.Add(b1); // von-Zeit-Box Binding b2 = new Binding("Text", bs, "von"); b2.Format += Zeit_Format; b2.Parse += Zeit_Parse; tb2.DataBindings.Add(b2); // bis-Zeit-Box Binding b3 = new Binding("Text", bs, "bis"); b3.Format += Zeit_Format; b2.Parse += Zeit_Parse; tb3.DataBindings.Add(b3); } private void Datum_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("dd.MM.yy"); } } private void Datum_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["von"]; e.Value = von_neu.Add(von_alt.TimeOfDay); DateTime bis_alt = (DateTime)row["bis"]; row["bis"]= von_neu.Add(bis_alt.TimeOfDay); } } } private void Zeit_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("HH:mm"); } } private void Zeit_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["von"]; e.Value = von_alt.Date.Add(von_neu.TimeOfDay); } } } } }
--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks- Als Antwort markiert Siegfried Reichmann Dienstag, 11. August 2015 01:47
-
Hi Siegfried,
ich vermute, dass Du Windows Forms nutzt. In diesem Fall kannst Du beim Binding-Objekt einen Format- und einen Parse-Handler nutzen. Du bindest die beiden ersten TextBoxes an das Von-Datenfeld und die dritte TextBox an das bis-Datenfeld. Im Format-Handler der ersten TextBox formatierst Du nur den Datumsteil als Zeichenkette für die Darstellung, im Format-Handler für die zweite und dritte TextBox formatierst Du nur den Zeitanteil als Zeichenkette für die Anzeige. In den Parse-Handler führst Du die umgekehrte Umwandlung aus und fügst dann Datums- und Zeit-Teil zusammen. Der Vorteil eigener Parse-Handler ist, dass der Anwender Datums- und Zeitangaben auch nach anderen Regeln eingeben kann, z.B. mit der Nummerntastatur ohne Trennzeichen (Punkt, Doppelpunkt). Der Parse-Handler prüft die Eingabe und wandelt dann nach den definierten Regeln die Eingabe passend um.--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen David Stania Dienstag, 4. August 2015 10:40
- Als Antwort markiert Aleksander Chalabashiev Dienstag, 11. August 2015 10:21
-
Hi Peter,
danke für Dein ausfühliches Beispiel. Ich habe den Code modifiziert und in mein Programm übernommen. Das anzeigen der Daten funktioniert prima, das Speichern aber nicht. Sobald ich nach dem Ändern des Datums oder einer Zeit das Control verlasse, springt es auf den ursprünglichen Wert zurück. Mein Code sieht so aus:
private void BindenDatumZeitControls() { Binding b1 = new Binding("Text", buchungBindingSource, "Von"); b1.Format += Datum_Format; b1.Parse += Datum_Parse; datumTextBox.DataBindings.Add(b1); // von-Zeit-Box Binding b2 = new Binding("Text", buchungBindingSource, "Von"); b2.Format += Zeit_Format; b2.Parse += Zeit_Parse; zeitVonTextBox.DataBindings.Add(b2); // bis-Zeit-Box Binding b3 = new Binding("Text", buchungBindingSource, "Bis"); b3.Format += Zeit_Format; b2.Parse += Zeit_Parse; zeitBisTextBox.DataBindings.Add(b3); } private void Datum_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("dd.MM.yyyy"); } } private void Datum_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["Von"]; e.Value = von_neu.Add(von_alt.TimeOfDay); DateTime bis_alt = (DateTime)row["Bis"]; row["Bis"] = von_neu.Add(bis_alt.TimeOfDay); } } } private void Zeit_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("HH:mm"); } } private void Zeit_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["Von"]; e.Value = von_alt.Date.Add(von_neu.TimeOfDay); } } }
Diese Zeilen habe ich als erste Zeilen in den Load Event des Forms eingefügt.
buchungDataGridView.DataSource = null; BindenDatumZeitControls(); buchungDataGridView.DataSource = buchungBindingSource;
Zuerst hatte ich nur das BindenDatumZeitControls(), die beiden anderen Zeilen waren ein Versuch.
Hast Du eine Idee warum das nur in eine Richtung funktioniert?
Viele Grüße
Siegfried
- Als Antwort vorgeschlagen Peter Fleischer Samstag, 8. August 2015 14:16
- Als Antwort markiert Aleksander Chalabashiev Dienstag, 18. August 2015 12:32
Alle Antworten
-
Hi Siegfried,
ich vermute, dass Du Windows Forms nutzt. In diesem Fall kannst Du beim Binding-Objekt einen Format- und einen Parse-Handler nutzen. Du bindest die beiden ersten TextBoxes an das Von-Datenfeld und die dritte TextBox an das bis-Datenfeld. Im Format-Handler der ersten TextBox formatierst Du nur den Datumsteil als Zeichenkette für die Darstellung, im Format-Handler für die zweite und dritte TextBox formatierst Du nur den Zeitanteil als Zeichenkette für die Anzeige. In den Parse-Handler führst Du die umgekehrte Umwandlung aus und fügst dann Datums- und Zeit-Teil zusammen. Der Vorteil eigener Parse-Handler ist, dass der Anwender Datums- und Zeitangaben auch nach anderen Regeln eingeben kann, z.B. mit der Nummerntastatur ohne Trennzeichen (Punkt, Doppelpunkt). Der Parse-Handler prüft die Eingabe und wandelt dann nach den definierten Regeln die Eingabe passend um.--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen David Stania Dienstag, 4. August 2015 10:40
- Als Antwort markiert Aleksander Chalabashiev Dienstag, 11. August 2015 10:21
-
Hi Siegfried,
nachfolgend eine kleine Demo am Beispiel einer Bindung mit einer DataTable:using System; using System.Data; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form02 : Form { public Form02() { InitializeComponent(); } TextBox tb1 = new TextBox() { Dock = DockStyle.Top }; TextBox tb2 = new TextBox() { Dock = DockStyle.Top }; TextBox tb3 = new TextBox() { Dock = DockStyle.Top }; DataGridView dgv = new DataGridView() { Dock = DockStyle.Fill }; private void Form02_Load(object sender, EventArgs e) { this.Controls.AddRange(new Control[] { dgv, tb3, tb2, tb1 }); DatenBinden(); } DataTable tab = new DataTable(); BindingSource bs = new BindingSource(); private void DatenBinden() { Random rnd = new Random(); // Tabelle tab.Columns.Add("von", typeof(DateTime)); tab.Columns.Add("bis", typeof(DateTime)); for (int i = 0; i < 10; i++) { tab.Rows.Add(DateTime.Now.AddMinutes(rnd.Next(1000)), DateTime.Now.AddMinutes(rnd.Next(2000))); } // BindingSource füllen bs.DataSource = tab; // Grid binden dgv.DataSource = bs; // von-Datums-Box Binding b1 = new Binding("Text", bs, "von"); b1.Format += Datum_Format; b1.Parse += Datum_Parse; tb1.DataBindings.Add(b1); // von-Zeit-Box Binding b2 = new Binding("Text", bs, "von"); b2.Format += Zeit_Format; b2.Parse += Zeit_Parse; tb2.DataBindings.Add(b2); // bis-Zeit-Box Binding b3 = new Binding("Text", bs, "bis"); b3.Format += Zeit_Format; b2.Parse += Zeit_Parse; tb3.DataBindings.Add(b3); } private void Datum_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("dd.MM.yy"); } } private void Datum_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["von"]; e.Value = von_neu.Add(von_alt.TimeOfDay); DateTime bis_alt = (DateTime)row["bis"]; row["bis"]= von_neu.Add(bis_alt.TimeOfDay); } } } private void Zeit_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("HH:mm"); } } private void Zeit_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["von"]; e.Value = von_alt.Date.Add(von_neu.TimeOfDay); } } } } }
--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks- Als Antwort markiert Siegfried Reichmann Dienstag, 11. August 2015 01:47
-
Hi Peter,
danke für Dein ausfühliches Beispiel. Ich habe den Code modifiziert und in mein Programm übernommen. Das anzeigen der Daten funktioniert prima, das Speichern aber nicht. Sobald ich nach dem Ändern des Datums oder einer Zeit das Control verlasse, springt es auf den ursprünglichen Wert zurück. Mein Code sieht so aus:
private void BindenDatumZeitControls() { Binding b1 = new Binding("Text", buchungBindingSource, "Von"); b1.Format += Datum_Format; b1.Parse += Datum_Parse; datumTextBox.DataBindings.Add(b1); // von-Zeit-Box Binding b2 = new Binding("Text", buchungBindingSource, "Von"); b2.Format += Zeit_Format; b2.Parse += Zeit_Parse; zeitVonTextBox.DataBindings.Add(b2); // bis-Zeit-Box Binding b3 = new Binding("Text", buchungBindingSource, "Bis"); b3.Format += Zeit_Format; b2.Parse += Zeit_Parse; zeitBisTextBox.DataBindings.Add(b3); } private void Datum_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("dd.MM.yyyy"); } } private void Datum_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["Von"]; e.Value = von_neu.Add(von_alt.TimeOfDay); DateTime bis_alt = (DateTime)row["Bis"]; row["Bis"] = von_neu.Add(bis_alt.TimeOfDay); } } } private void Zeit_Format(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(DateTime) && e.DesiredType == typeof(string)) { DateTime d = (DateTime)e.Value; e.Value = d.ToString("HH:mm"); } } private void Zeit_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["Von"]; e.Value = von_alt.Date.Add(von_neu.TimeOfDay); } } }
Diese Zeilen habe ich als erste Zeilen in den Load Event des Forms eingefügt.
buchungDataGridView.DataSource = null; BindenDatumZeitControls(); buchungDataGridView.DataSource = buchungBindingSource;
Zuerst hatte ich nur das BindenDatumZeitControls(), die beiden anderen Zeilen waren ein Versuch.
Hast Du eine Idee warum das nur in eine Richtung funktioniert?
Viele Grüße
Siegfried
- Als Antwort vorgeschlagen Peter Fleischer Samstag, 8. August 2015 14:16
- Als Antwort markiert Aleksander Chalabashiev Dienstag, 18. August 2015 12:32
-
Hi Siegfried,
ich kann am Code keinen Unterschied erkennen. Bei mir funktionieren auch die Änderungen. Sobald ich eine TextBox verlasse, steht da der geänderte Wert drin und sobald ich im DataGridView ein Refresh (z.B. anderen Datensatz selektieren) ausführe, wird die Anzeige auch aktualisiert.--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks -
Hi Peter,
ich habe Deinen Code um einen try/catch Block erweitert und bekomme die unten stehende Exception.
private void Datum_Parse(object sender, ConvertEventArgs e) { if (e.Value.GetType() == typeof(string) && e.DesiredType == typeof(DateTime)) { DateTime von_neu; if (DateTime.TryParse(e.Value.ToString(), out von_neu)) { try { Binding b = (Binding)sender; CurrencyManager cm = (CurrencyManager)b.BindingManagerBase; DataRowView drv = (DataRowView)cm.Current; DataRow row = drv.Row; DateTime von_alt = (DateTime)row["Von"]; e.Value = von_neu.Add(von_alt.TimeOfDay); DateTime bis_alt = (DateTime)row["Bis"]; row["Bis"] = von_neu.Add(bis_alt.TimeOfDay); } catch (Exception ex) { clsDisplayException.show(ex, "öööö"); } } } }
Die untenstehende Exception wird beim Ausführen dieser Anweisung generiert:
DataRowView drv = (DataRowView)cm.Current;
Viele Grße
Siegfried
-
Hi,
über Deine Bedingungen hast Du nichts geschrieben. Wenn Deine Bedingungen von meinem Beispiel, welches vollständig ist, abweichen, musst Du den Code an Deine Bedingungen anpassen, speziell an den Typ der anzuzeigenden Datenobjekte. In meinem Beispiel habe ich eine BindingSource mit DataTable als Datenpuffer genutzt. Die BindingSource erzeugt intern eine DataView für die Daten der DataTable und einen BindingManager, deren aktuelles Element für den konkreten Bindungsfall eine DataRowView ist. Was es bei Dir ist, kann ich wegen fehlendem Code in deinen Auszügen nicht sagen. Die Fehlerausschrift sagt aus, dass Du EDM nutzt.
--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks
- Bearbeitet Peter Fleischer Donnerstag, 6. August 2015 04:55
-
-
Hi Siegfried,
damit Du genau erkennen kannst, wie im Parse-Ereignis zu verfahren ist, hatte ich alle Schritte in einzelnen Anweisungen ausgeführt. Die endgültige Lösung kann viel kürzer programmiert werden, was aber nicht unbedingt der Übersichtlichkeit dient.--
Viele Grüsse
Peter Fleischer (MVP, Partner)
Meine Homepage mit Tipps und Tricks