Laden...

DateTimePickerColumn im DataGridView

Erstellt von ErfinderDesRades vor 15 Jahren Letzter Beitrag vor 15 Jahren 7.873 Views
ErfinderDesRades Themenstarter:in
5.299 Beiträge seit 2008
vor 15 Jahren
DateTimePickerColumn im DataGridView

Je nach angewendetem FormatString stellt ein DateTimePicker sich unterschiedlich dar.
In diesem Snippet wird dieses Verhalten auf die ganze Column übertragen, man kann ja dem Celltemplate der Column einen Formatstring zuweisen.

Also kann diese Column sowohl Datums als auch Uhrzeiten editieren, und die üblichen Mixturen, die man sich mit einem FormatString zusammenbasteln kann.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Globalization;

namespace TimePickerColumnTest {
   //das Hosten eines Controls in einer einer DataGridViewColumn erfordert 3 Klassen:
   //1) die neue DataGridViewColumn
   //2) die Standard-Zelle dieser Column, wenn nicht editiert wird
   //3) das Editing-Control, mit dem Zellwerte editiert werden können - muß IDataGridViewEditingControl implementieren

   //hohe Flexiblität wird erreicht, indem der verwendete DateTimePicker mit dem FormatString des CellTemplates der TimePickerColumn gefüttert wird.

   public class TimePickerColumn : DataGridViewColumn {

      public TimePickerColumn() : base(new TimePickerCell()) { }

      public override DataGridViewCell CellTemplate {
         get { return base.CellTemplate; }
         set {
            if (value != null && !(value is TimePickerCell)) {
               //das lass ich so. Weil ich finds lustig, daß man sieht, dassich von einer türkischen Vorlage abgekupfert hab
               throw new InvalidCastException("Tip Uyusmazligi");
            }
            base.CellTemplate = value;
         }
      }
   }

   public class TimePickerCell : DataGridViewTextBoxCell {
      public override void InitializeEditingControl(
            int rowIndex, object initialFormattedValue, DataGridViewCellStyle cellStyle) {
         base.InitializeEditingControl(rowIndex, initialFormattedValue, cellStyle);
         if (Convert.IsDBNull(this.Value)) return;
         ((TimePickerEditingControl)DataGridView.EditingControl).Value = (DateTime)this.Value;
      }
      public override Type EditType { get { return typeof(TimePickerEditingControl); } }
      public override Type ValueType { get { return typeof(DateTime); } }
      public override object DefaultNewRowValue { get { return DateTime.Now; } }
   }


   public class TimePickerEditingControl : DateTimePicker, IDataGridViewEditingControl {
      //DateTimePicker kann sich wunderbar auf Zeit-Format-Strings einstellen. Probleme hatter mit den vorgefertigten Kurzformen der Zeitformate. Daher werden diese in einem Dictionary mit ihrer kulturabhängigen ausführlichen Schreibweise assoziiert.
      private static Dictionary<string, string> _Patterns = new Dictionary<string, string>();

      static TimePickerEditingControl() {
         var DTFI = CultureInfo.CurrentCulture.DateTimeFormat;
         _Patterns.Add("d", DTFI.ShortDatePattern);
         _Patterns.Add("D", DTFI.LongDatePattern);
         _Patterns.Add("t", DTFI.ShortTimePattern);
         _Patterns.Add("T", DTFI.LongTimePattern);
         _Patterns.Add("g", DTFI.ShortDatePattern + " " + DTFI.ShortTimePattern);
         _Patterns.Add("G", DTFI.LongDatePattern + " " + DTFI.LongTimePattern);
         _Patterns.Add("", _Patterns["g"]);
   }

      public TimePickerEditingControl() { base.Format = DateTimePickerFormat.Custom; }

      #region IDataGridViewEditingControl Members

      public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle) {
         this.Font = dataGridViewCellStyle.Font;
         this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
         this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
         var f = dataGridViewCellStyle.Format;
         base.CustomFormat = _Patterns.ContainsKey(f) ? _Patterns[f] : f;
      }
      public DataGridView EditingControlDataGridView { get; set; }
      public int EditingControlRowIndex { get; set; }
      public bool EditingControlValueChanged { get; set; }
      public Cursor EditingPanelCursor { get { return base.Cursor; } }
      public bool RepositionEditingControlOnValueChange { get { return false; } }
      public object EditingControlFormattedValue {
         get { return this.Value.ToString(base.CustomFormat); }
         set { if (value is string) { this.Value = DateTime.Parse((string)value); } }
      }
      public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey) {
         switch (keyData) {
            case Keys.Left:
            case Keys.Up:
            case Keys.Down:
            case Keys.Right:
            case Keys.Home:
            case Keys.End:
            case Keys.PageDown:
            case Keys.PageUp:
               return true;
            default:
               return false;
         }
      }
      public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) {
         return this.EditingControlFormattedValue;
      }
      public void PrepareEditingControlForEdit(bool selectAll) {
         //Kontrolümüzü editmele moduna haz1rlamak için herhangi bir i_lem yapmayaca1z.
      }
      protected override void OnValueChanged(EventArgs eventargs) {
         EditingControlValueChanged = true;
         this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
         base.OnValueChanged(eventargs);
      }

      #endregion IDataGridViewEditingControl Members
   }
}

Der frühe Apfel fängt den Wurm.

J
3.331 Beiträge seit 2006
vor 15 Jahren

Hallo,

nach den Rückfragen der letzten Zeit scheint eine solche Lösung sinnvoll zu sein; danke schön!

Ich habe es noch nicht genauer untersucht und getestet, sehe aber ein Problem darin, dass die möglichen **Patterns **nur im EditingControl enthalten sind. Das bedeutet zwar, dass sie im Edit-Modus berücksichtigt werden. Aber wäre es nicht sinnvoller, dass der Nutzer im Designer ein Pattern auswählen könnte und dies dann in der ganzen Spalte (d.h. jeder TimePickerCell) als Eigenschaft registriert würde?

So hatte ich es bei MaskedTextBox in einer DataGridViewColumn mit der Mask-Eigenschaft gemacht.

/Edit
Vielleicht hast Du es auch so gemacht, und nur der obige Code ist verkürzt?

Gruß Jürgen

PS. Mein TR-Wörterbuch habe ich vor Jahren entsorgt. Leider kann man diese Zeichen (she, yumushak-g, i ohne Punkt) im Forum kaum richtig schreiben, und die Übersetzung wäre auch schön. 😉

ErfinderDesRades Themenstarter:in
5.299 Beiträge seit 2008
vor 15 Jahren

nee, es sind alle Pattern möglich, mit denen DateTime formatiert ausgegeben werden kann: "yyyy-MMM-dd....hh:mm:ss" - was du wolle. Nur gibt es außerdem noch gültige Kurzschreibweisen, etwa "d" entspricht in deutsch-Kultur: "dd.MM.yy".
Und diese Kurzschreibweisen, da stellt sich der DateTimePicker ungeschickt mit an, sodaß ich ihm ein Dictionary verpasst habe, mit dem er die Kurzschreibweisen in lang ausgeschriebene Formate übersetzt.

Der gezeigte Code ist vollständig.

Der frühe Apfel fängt den Wurm.