Скрытие текста DateTimePicker и изменение размера Usercontrol
У меня есть пользовательский элемент управления, который имеет DateTimePicker, наложенный на однострочное текстовое поле (Tb)
охватывающий текстовую часть DateTimePicker. Текстовое поле Tb (зеленый) закреплено (L T R B).
Проблема возникает, когда пользовательский контроль изменяется.
Наложенный указатель даты и времени отображается за текстом Tb.
В настоящее время пользовательский контроль составляет 242(Ш) х 20(В). Проблемы появляются, когда размер элемента управления меньше 100 (ширина).
Я попытался очистить текст с CustomFormat, установленным в " ", но пользовательский элемент управления поддерживает многие функции datetimepicker, поэтому это было невозможно.
Я попытался установить минимальный размер пользовательского элемента управления, но это тоже не работает.
Редактировать:
Элемент управления уже используется в нескольких приложениях. В этих приложениях минимальный размер элемента управления составляет 90X20, тогда как минимальный размер, который мы устанавливаем сейчас, составляет 97x20.
Будет ли VS разработчик изменить размеры существующих элементов управления до 97x20 после внесения изменений?
Как добиться этого эффекта (изменить размер до 97x20)?
Изменить код **** после добавления минимального размера ****
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;
}
}
Изменить: после добавления минимальных размеров, выглядит лучше, но выпадающий список каландра исчезает
когда размер элемента управления уменьшен до минимума и проект перестроен.
Также текстовое поле не остается закрепленным рядом с кнопкой каландра.
редактировать: рис добавлен для выше.. календарь исчезает.
Изменить: О, я пропустил еще одну вещь, и поле даты и время складываются. Вот почему разделенный контейнер есть. При подсчете минимального размера также следует помнить об этом (я думаю, 2 разных минимальных размера в зависимости от видимости временного поля).
Вопросы:
а) Как я могу предотвратить изменение размера пользовательского элемента управления за пределы определенного минимального предела, чтобы избежать вышеуказанной проблемы? (рис.1, кажется, размер идеи)
б) Могу ли я нарисовать datetimepicker таким образом, чтобы текст был отключен, и мы видим только
кнопка выпадающего списка? Если так, то мне все еще нужно будет обрабатывать события изменения размера?
c) Как я могу продолжать изменять размер текстового поля, чтобы оно всегда покрывало текстовую часть даты DTP.
2 ответа
У вас есть простая проблема и сложная проблема. Простая проблема очевидна из скриншотов. DateTimePicker неправильно изменяет размеры, обратите внимание, как выпадающая кнопка застревает с правой стороны. UserControl слишком странный, чтобы действительно определить проблему, но я думаю, что это datePanel. Вы используете Anchor.Right вместо Dock.Fill.
Сложная проблема заключается в том, что выпадающая кнопка динамически изменяет свой размер в зависимости от объема пространства, доступного для визуализации содержимого DTP. По крайней мере, в Windows 7 более ранние версии используют другую стратегию рендеринга. К сожалению, API VisualStyles не возвращает фактический размер кнопки. Единственный достойный способ справиться с этим - убедиться, что текстовое поле достаточно велико, чтобы покрыть значок, чтобы была видна только стрелка раскрывающегося списка.
Я ничего не могу сделать с UserControl, я предложу гораздо более простое решение, которое просто происходит от класса DateTimePicker и встраивает в него TextBox. Также намного дешевле во время выполнения:
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 заботится о сохранении правильного размера TextBox. Добавьте любой код для обработки свойства editbox.Text. Единственная деталь, о которой не заботятся, это размер раскрывающейся кнопки, когда визуальные стили отключены. Нечасто в эти дни, но все еще возможно. Выключите тему на вашем компьютере и настройте жестко запрограммированный размер, чтобы он соответствовал внешнему виду.
Я не думаю, что вы получите хороший результат, наложив DateTimePicker на текстовое поле. Всегда будут проблемы изменения размера и фокуса.
Я бы использовал один из этих вариантов:
- Используйте сторонний элемент управления, такой как DevExpress PopupContainerEdit. Затем вы можете открыть стандартный WindowsForms MonthCalendar и настроить отображаемый текст в соответствии с требованиями. Я уверен, что аналогичные элементы управления доступны от Telerik и т. Д.
Используйте или настройте аналогичный выпадающий контейнерный элемент управления, например, Code Project. Есть как минимум два, которые вы можете использовать в качестве вдохновения:
Вы даже можете адаптировать выпадающую часть моего палитры цветов в проекте кода
Последний вариант, который даст вам больше гибкости, - это перейти с WindowsForms на WPF. Создавать пользовательские элементы управления, такие как это, намного проще (в любом случае, после крутой кривой обучения).