2012-04-05 8 views
7

Ho un controllo utente che ha un DateTimePicker sovrapposto alla casella di testo a riga singola (Tb)
che copre la parte di DateTimePicker. La casella di testo Tb (verde) è ancorata (L T R B).Hiding DateTimePicker's text e Usercontrol ridimensionare

Datepicker overlaid with textbox

Il problema nasce quando l'UserControl viene ridimensionato.
Il datetepeper sovrapposto si trova dietro il testo Tb.

The overlaid datetimepicker shows up behind the green textbox Tb.

Attualmente il controllo utente è 242 (W) x 20 (H). I problemi si presentano quando il controllo viene ridimensionato al di sotto di 100 (larghezza).

Ho provato a vuoto il testo con CustomFormat impostato su "" ma il controllo utente supporta molte delle funzionalità datetimepicker in modo che non fosse un'opzione.

Ho provato a impostare la dimensione minima sul controllo utente ma non funziona.

Edit:
Il controllo è già in uso in alcuni applications.In quelle applicazioni la dimensione minima del controllo è 90X20 mentre la dimensione minima che abbiamo impostato ora è 97x20.
Il progettista VS ridimensiona i controlli esistenti a 97x20 dopo aver apportato la modifica?
Come ottenere questo effetto (ridimensiona a 97x20)?

Modifica **** codice dopo l'aggiunta di dimensione minima ****

namespace WindowsFormsApplication1 
{ 
    partial class CDatePicker 
    { 
     private System.ComponentModel.IContainer components = null; 


     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Component Designer generated code 


     private void InitializeComponent() 
     { 
      this.splitContainer1 = new System.Windows.Forms.SplitContainer(); 
      this.datepanel = new System.Windows.Forms.Panel(); 
      this.datetxt = new System.Windows.Forms.TextBox(); 
      this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); 
      this.timepanel = new System.Windows.Forms.Panel(); 
      this.timetxt = new System.Windows.Forms.TextBox(); 
      ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); 
      this.splitContainer1.Panel1.SuspendLayout(); 
      this.splitContainer1.Panel2.SuspendLayout(); 
      this.splitContainer1.SuspendLayout(); 
      this.datepanel.SuspendLayout(); 
      this.timepanel.SuspendLayout(); 
      this.SuspendLayout(); 
      // 
      // splitContainer1 
      // 
      this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; 
      this.splitContainer1.Location = new System.Drawing.Point(0, 0); 
      this.splitContainer1.Name = "splitContainer1"; 
      // 
      // splitContainer1.Panel1 
      // 
      this.splitContainer1.Panel1.Controls.Add(this.datepanel); 
      this.splitContainer1.Panel1MinSize = 105; 
      // 
      // splitContainer1.Panel2 
      // 
      this.splitContainer1.Panel2.Controls.Add(this.timepanel); 
      this.splitContainer1.Size = new System.Drawing.Size(236, 20); 
      this.splitContainer1.SplitterDistance = 178; 
      this.splitContainer1.SplitterWidth = 1; 
      this.splitContainer1.TabIndex = 0; 
      // 
      // datepanel 
      // 
      this.datepanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
      | System.Windows.Forms.AnchorStyles.Left) 
      | System.Windows.Forms.AnchorStyles.Right))); 
      this.datepanel.Controls.Add(this.datetxt); 
      this.datepanel.Controls.Add(this.dateTimePicker1); 
      this.datepanel.Location = new System.Drawing.Point(0, 0); 
      this.datepanel.Margin = new System.Windows.Forms.Padding(0); 
      this.datepanel.Name = "datepanel"; 
      this.datepanel.Size = new System.Drawing.Size(175, 20); 
      this.datepanel.TabIndex = 0; 
      // 
      // datetxt 
      // 
      this.datetxt.BackColor = System.Drawing.Color.Gainsboro; 
      this.datetxt.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; 
      this.datetxt.Location = new System.Drawing.Point(0, 0); 
      this.datetxt.MinimumSize = new System.Drawing.Size(60, 20); 
      this.datetxt.Name = "datetxt"; 
      this.datetxt.Size = new System.Drawing.Size(71, 20); 
      this.datetxt.TabIndex = 3; 
      this.datetxt.Text = "date"; 
      // 
      // dateTimePicker1 
      // 
      this.dateTimePicker1.Dock = System.Windows.Forms.DockStyle.Fill; 
      this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Short; 
      this.dateTimePicker1.Location = new System.Drawing.Point(0, 0); 
      this.dateTimePicker1.Margin = new System.Windows.Forms.Padding(0); 
      this.dateTimePicker1.MinimumSize = new System.Drawing.Size(65, 20); 
      this.dateTimePicker1.Name = "dateTimePicker1"; 
      this.dateTimePicker1.Size = new System.Drawing.Size(175, 20); 
      this.dateTimePicker1.TabIndex = 2; 
      this.dateTimePicker1.Value = new System.DateTime(2012, 11, 15, 0, 0, 0, 0); 
      // 
      // timepanel 
      // 
      this.timepanel.Controls.Add(this.timetxt); 
      this.timepanel.Dock = System.Windows.Forms.DockStyle.Fill; 
      this.timepanel.Location = new System.Drawing.Point(0, 0); 
      this.timepanel.Margin = new System.Windows.Forms.Padding(0); 
      this.timepanel.Name = "timepanel"; 
      this.timepanel.Size = new System.Drawing.Size(57, 20); 
      this.timepanel.TabIndex = 0; 
      // 
      // timetxt 
      // 
      this.timetxt.Dock = System.Windows.Forms.DockStyle.Fill; 
      this.timetxt.Location = new System.Drawing.Point(0, 0); 
      this.timetxt.Name = "timetxt"; 
      this.timetxt.Size = new System.Drawing.Size(57, 20); 
      this.timetxt.TabIndex = 1; 
      this.timetxt.Text = "time"; 
      this.timetxt.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; 
      // 
      // CDatePicker 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.AutoSize = true; 
      this.Controls.Add(this.splitContainer1); 
      this.MaximumSize = new System.Drawing.Size(236, 20); 
      this.MinimumSize = new System.Drawing.Size(100, 20); 
      this.Name = "CDatePicker"; 
      this.Size = new System.Drawing.Size(236, 20); 
      this.splitContainer1.Panel1.ResumeLayout(false); 
      this.splitContainer1.Panel2.ResumeLayout(false); 
      ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); 
      this.splitContainer1.ResumeLayout(false); 
      this.datepanel.ResumeLayout(false); 
      this.datepanel.PerformLayout(); 
      this.timepanel.ResumeLayout(false); 
      this.timepanel.PerformLayout(); 
      this.ResumeLayout(false); 

     } 

     #endregion 

     private System.Windows.Forms.SplitContainer splitContainer1; 
     private System.Windows.Forms.Panel datepanel; 
     private System.Windows.Forms.TextBox datetxt; 
     private System.Windows.Forms.DateTimePicker dateTimePicker1; 
     private System.Windows.Forms.Panel timepanel; 
     private System.Windows.Forms.TextBox timetxt; 
    } 
} 

Edit: Dopo aver aggiunto min dimensioni, sembra meglio, ma il calendario a discesa scompare
quando il controllo viene ridimensionato a min e il progetto viene ricostruito ..
Anche la casella di testo non rimane ancorata vicino al pulsante di calendario ..

modifica: immagine aggiunta per sopra..calender scompare.

date calender disappears

Edit: Oh mi mancava ancora una cosa sia il campo della data e il campo ora sono collapsible.thats il motivo per cui il contenitore split è lì. calcoli dimensioni minime devono essere consapevoli di questo (credo 2 differenti min dimensioni a seconda della visibilità di campo tempo..)

Domande:.

a) Come posso evitare che l'UserControl di ridimensionare oltre certi limite minimo per evitare il problema sopra? (la foto sembra essere una dimensione idea)

b) Posso disegnare il datetimepicker in modo tale che il testo sia cancellato e vediamo solo il pulsante a tendina del calendario
? In caso affermativo avrò ancora bisogno di gestire gli eventi di ridimensionamento?

c) Come posso continuare a ridimensionare la casella di testo in modo che copra sempre la parte di DTP del testo della data.

+0

Cosa intendi con * "Ho provato a impostare la dimensione minima sul controllo utente ma non funziona troppo" *? Dovrebbe forzare il controllo a ridimensionare solo fino a un certo limite minimo. Che cosa esattamente non ha funzionato? – alex

+0

Dal designer dello studio visivo ho impostato la dimensione minima sull'usercontrol .. ma quando il controllo è posizionato su un modulo, l'utente finale può modificare quella dimensione minima su (0,0) e quindi il controllo può essere ridimensionato sotto il dimensione minima (come si vede nella seconda foto) – Amitd

+0

Posso chiedere perché sovrapponi un controllo casella di testo sul DateTimePicker (dtp), non ho approfondito il controllo ma ho potuto indovinare il dtp sarebbe una casella di testo con un menu a discesa controllo del calendario.Potrei sbagliarmi, ma sembra che tu voglia far funzionare il tuo controllo utente dal controllo del dtp - usa reflector o dotpeek sulla System.Windows.Forms dll –

risposta

3

Hai un problema semplice e un problema difficile. Il semplice problema è evidente dagli screenshot. DateTimePicker non sta ridimensionando correttamente, nota come il pulsante a discesa viene ritagliato sul lato destro. UserControl è troppo strano per individuare veramente il problema, ma penso che sia il datePanel. Stai utilizzando Anchor.Right anziché Dock.Fill.

Il difficile problema è che il pulsante a discesa si ridimensiona dinamicamente, in base alla quantità di spazio disponibile per il rendering del contenuto DTP. Almeno su Windows 7, le versioni precedenti utilizzano una diversa strategia di rendering. Purtroppo, l'API di VisualStyles non restituisce la dimensione effettiva del pulsante. L'unico modo decente per affrontarlo è assicurarsi che la casella di testo sia abbastanza grande da coprire l'icona in modo che solo la freccia a discesa sia visibile.

Non riesco a fare molto con l'UserControl, proporrò una soluzione molto più semplice che deriva dalla classe DateTimePicker e incorpora un TextBox al suo interno. Anche un sacco più economico in fase di esecuzione:

using System; 
using System.Drawing; 
using System.Windows.Forms; 
using System.Windows.Forms.VisualStyles; 
using System.Runtime.InteropServices; 

class MyDateTimePicker : DateTimePicker { 
    private TextBox editbox; 
    private int buttonWidth; 

    public MyDateTimePicker() { 
     editbox = new TextBox(); 
     editbox.BorderStyle = BorderStyle.None; 
     editbox.BackColor = Color.Gold; // debugging 
     this.Controls.Add(editbox); 
    } 

    public override Font Font { 
     get { return base.Font; } 
     set { base.Font = editbox.Font = value; } 
    } 

    protected override void OnResize(EventArgs e) { 
     if (buttonWidth == 0) measureButtonWidth(); 
     var margin = (this.ClientSize.Height - editbox.PreferredHeight)/2; 
     editbox.Location = new Point(margin, margin); 
     editbox.Width = this.ClientSize.Width - margin - buttonWidth; 
     base.OnResize(e); 
    } 

    private void measureButtonWidth() { 
     if (!Application.RenderWithVisualStyles) buttonWidth = 21; // TODO: measure 
     else { 
      var renderer = new VisualStyleRenderer("DATEPICKER", 3, 1); 
      using (var gr = CreateGraphics()) { 
       buttonWidth = renderer.GetPartSize(gr, ThemeSizeType.True).Height; 
      } 
     } 
    } 

    protected override void Dispose(bool disposing) { 
     if (disposing) editbox.Dispose(); 
     base.Dispose(disposing); 
    } 
} 

L'override OnResize si prende cura di mantenere il controllo TextBox la giusta dimensione. Aggiungi qualunque codice tu abbia per elaborare la proprietà editbox.Text. L'unico dettaglio non curato è la dimensione del pulsante a discesa quando gli stili visivi sono disabilitati. Non comune in questi giorni ma ancora possibile. Disattiva i temi sulla tua macchina e modifica le dimensioni hard-coded in modo che corrispondano all'aspetto.

+0

+1 grazie controllerò e ti ricontatterei. – Amitd

+0

thx @Hans Passant ... ho finito per seguire il tuo approccio ... molto più semplice e facile da capire. Un po 'di mix and match. – Amitd

+0

Un'altra cosa interessante che ho scoperto è stata questa domanda SO http://stackoverflow.com/questions/154543/panel-dock-fill-ignoring-other-panel-dock-setetting – Amitd

0

Non penso che otterrete un buon risultato sovrapponendo DateTimePicker a una casella di testo. Ci saranno sempre dei problemi di ridimensionamento e messa a fuoco.

vorrei utilizzare una di queste opzioni:

  • Utilizzare un controllo di terza parte come DevExpress PopupContainerEdit. È quindi possibile visualizzare il MonthCalendar standard di Windows Form e personalizzare il testo visualizzato come richiesto. Sono sicuro che controlli simili sono disponibili da Telerik, ecc.
  • Utilizzare o personalizzare un controllo contenitore a discesa simile da qualche parte come il Progetto codice. Ci sono almeno due si potrebbe usare come ispirazione:

  • Si potrebbe anche adattare la discesa parte della mia colour picker sul Progetto Codice

Un'ultima opzione, che ti darebbe maggiore flessibilità, è passare da Windows Form a WPF. Creare controlli personalizzati come questo è molto più semplice (anche dopo la curva di apprendimento ripida).