2012-04-05 8 views
7

Mam kontrolę użytkownika, która ma nałożony obiekt DateTimePicker z pojedynczym polem tekstowym (Tb)
obejmującym część tekstową obiektu DateTimePicker. Pole tekstowe Tb (green) jest zakotwiczone (L T R B).Ukrywanie obiektu DateTimePicker i zmiana rozmiaru kontrolki użytkownika

Datepicker overlaid with textbox

Problem pojawia się, gdy UserControl jest zmieniany.
Nakładany datetimepicker pojawia się za tekstem Tb.

The overlaid datetimepicker shows up behind the green textbox Tb.

Obecnie kontroli użytkownika 242 (W) x 20 (h). Problemy pojawiają się, gdy rozmiar kontrolki jest mniejszy niż 100 (szerokość).

Próbowałem pusty tekst z CustomFormat ustawionym na "", ale formant użytkownika obsługuje wiele funkcji datetimepicker, więc nie było opcji.

Próbowałem ustawić minimalny rozmiar na formancie użytkownika, ale to też nie działa.

Edit:
Sterowanie jest już w użyciu w kilku applications.In te aplikacje minimalna wielkość sterująca jest 90X20 natomiast minimalna wielkość, która jest teraz ustawiony 97x20.
Czy projektant VS wymieni istniejące elementy sterujące na 97 x 20 po wprowadzeniu zmiany?
Jak osiągnąć ten efekt (zmiana rozmiaru na 97x20)?

Edit **** Kod po dodaniu minimalnej wielkości ****

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; 
    } 
} 

Edycja: Po dodaniu min rozmiary, wygląda lepiej, ale kalendarz rozwijanej znika
gdy kontrola jest zmieniany do min i projekt jest przebudowywany.
Również pole tekstowe nie pozostaje zakotwiczone w pobliżu przycisku kalendarza.

edytuj: zdjęcie dodane dla powyższego ... Skalowanie zniknęło.

date calender disappears

Edit: Oh brakowało mi jeszcze jedną rzecz zarówno pole data i czas są collapsible.thats pole dlaczego pojemnik podziału jest tam. Obliczenia minimalna wielkość musi być świadomy tego (chyba 2 różne min rozmiary w zależności od widoczności dziedzinie czasu.).

Pytania:.

a) W jaki sposób można zapobiec usercontrol od rozmiaru poza pewne minimalny limit, aby uniknąć powyższego problemu? (pic1 wydaje się być wielkością pomysłu)

b) Czy mogę narysować datetimicker tak, że tekst jest pusty i widzimy tylko przycisk rozwijania kalendarza
? Jeśli tak, czy nadal będę musiał obsługiwać zdarzenia zmiany rozmiaru?

c) Jak mogę zmienić rozmiar pola tekstowego tak, aby zawsze obejmował tekst DTP.

+0

Co masz na myśli przez "Próbowałem ustawić minimalny rozmiar na kontrolerze użytkownika, ale to też nie działa" *? Powinno to zmusić kontroler do zmiany rozmiaru tylko do pewnego minimalnego limitu. Co dokładnie nie działa? – alex

+0

Od projektanta Visual studio ustawiłem Minimalny rozmiar na sterowaniu użytkownika .. ale kiedy formant jest umieszczony na formularzu, użytkownik końcowy może zmienić ten minimalny rozmiar na (0,0), a następnie można zmienić rozmiar kontrolki poniżej Minimalny rozmiar (jak widać na drugim zdjęciu) – Amitd

+0

Czy mogę zapytać, dlaczego nakładka na formant pole tekstowe na DateTimePicker (dtp), nie zagłębić się w kontroli, ale mogę zgadywać, że dtp byłoby pole tekstowe z listy rozwijanej kontrola kalendarza.Mogę się mylić, ale wygląda na to, że możesz chcieć, aby twoje własne sterowanie użytkownika wyszło z kontrolki dtp - użyj reflektora lub dotpeek w System.Windows.Forms dll –

Odpowiedz

3

Masz prosty problem i trudny problem. Prosty problem wynika z zrzutów ekranu. DateTimePicker nie zmienia rozmiaru poprawnie, zwróć uwagę, jak przycisk rozwijania jest przycinany po prawej stronie. UserControl jest zbyt dziwny, aby naprawdę zidentyfikować problem, ale myślę, że jest to datePanel. Używasz Anchor.Right zamiast Dock.Fill.

Trudnym problemem jest to, że przycisk rozwijany zmienia się dynamicznie, w zależności od ilości miejsca dostępnego do renderowania zawartości DTP. Przynajmniej w systemie Windows 7 wcześniejsze wersje używają innej strategii renderowania. Niestety interfejs VisualStyles nie zwraca rzeczywistego rozmiaru przycisku. Jedynym godnym sposobem na rozwiązanie tego problemu jest upewnienie się, że pole tekstowe jest wystarczająco duże, aby ukryć ikonę, więc widoczna jest tylko strzałka w dół.

Nie mogę wiele zrobić z UserControl, zaproponuję znacznie prostsze rozwiązanie, które wywodzi się z klasy DateTimePicker i osadza w niej TextBox. Również dużo tańsze w czasie wykonywania:

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); 
    } 
} 

OnResize przesłanianie dba o utrzymanie pola tekstowego odpowiedni rozmiar. Dodaj dowolny kod do przetworzenia właściwości editbox.Text. Jedynym szczegółem, który nie został rozwiązany, jest rozmiar przycisku rozwijania, gdy style wizualne są wyłączone. Niezbyt często w tych dniach, ale nadal możliwe. Wyłącz motywy na swoim komputerze i dostosuj rozmiar zakodowanego dysku tak, aby pasował do wyglądu.

+0

+1 dzięki. Sprawdzę i skontaktuję się z Tobą. – Amitd

+0

thx @Hans Passant ... Skończyło się na twoim podejściu .. o wiele prostszym i łatwiejszym do zrozumienia. Trochę wymieszać i dopasować. – Amitd

+0

Inną interesującą rzeczą, jaką odkryłem, było to pytanie: http://stackoverflow.com/questions/154543/panel-dock-fill-ignoring-other-panel-dock-setting – Amitd

0

Nie sądzę, że uzyskasz dobry wynik, nakładając narzędzie DateTimePicker na pole tekstowe. Zawsze będą występować problemy ze zmianą rozmiaru i ostrości.

chciałbym skorzystać z jednej z tych opcji:

  • Użyj trzeci kontroli partii jak DevExpress PopupContainerEdit. Następnie można wyskoczyć standardowy kalendarz formularzy Windows Forms MonthCalendar i dostosować wyświetlany tekst zgodnie z wymaganiami. Jestem pewien, że podobne elementy sterujące są dostępne od Telerik, itp.
  • Użyj lub dostosuj podobny kontrolek do rozwijanego kontenera z miejsca takiego jak Code Project. Istnieją co najmniej dwa można użyć jako inspiracja:

  • Można nawet dostosować rozwijaną częścią mojego colour picker o projekcie Kodeksu

Ostatnią opcją, która zapewnia większą elastyczność, jest przejście z Windows Forms do WPF. Tworzenie takich niestandardowych kontrolek jest o wiele łatwiejsze (i tak po stromej krzywej uczenia się).

Powiązane problemy