Как наследовать базовое Textbox для предоставления цветных границ - PullRequest
2 голосов
/ 11 февраля 2010

У меня есть приложение winform, которое мы используем дома. Он имеет много отдельных элементов управления на каждой из 25 «страниц» (usercontrols). Наша пользовательская база предпочитает очень технические приложения ... они хотят, чтобы TextBox был выделен синим цветом, если это обязательное поле (цвет должен исчезнуть, если введены данные). Они хотят, чтобы TextBox изменил цвет на зеленый, если в нем были изменены данные, чтобы напомнить им о необходимости сохранения. Они хотят, чтобы в данный момент выделенный текстовый блок был выделен RedOrange.

Я пытался прийти к этому с разных сторон (некоторые из вас, вероятно, видели подобные сообщения в последнее время). Ни один из них не работает ... Так что один из способов, которым я ЗНАЮ, будет работать, это зарегистрировать событие рисования для каждого элемента управления и проверить наличие «обязательного» тега для требуемой части. OnFocus для текущей части поля и, наконец, событие Validate для измененной части данных.

Я знаю, что это не лучший способ, или, по крайней мере, я НАСТОЯТЕЛЬНО подозреваю, что это не так, но у меня почти нет времени, и я близок к своему разочарованию. Это сказало, разрушит ли отзывчивость моего приложения? Есть ли способ лучше? Могу ли я переопределить базовый элемент управления для цвета в разных помещениях, чтобы мне не приходилось переходить к каждому из 100+ элементов управления?

Любая идея приветствуется, потому что я нахожусь между моей глупой идеей Paint_Event и переписываю все элементы управления в WPF ...:)

Я буду вознагражден решением, которое работает для меня и которое я вскоре смогу реализовать с помощью Bounty.

Мне так надоели цвета ...


Вот моя попытка, основанная на предложениях.

public class MyTextBox : TextBox
{
    private bool _isRequired;
    public bool isRequired
    {
        get
        {
            return _isRequired;
        }
        set
        {
            _isRequired = value;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (isRequired && base.Text.Equals(string.Empty))
        {
            HighlightControl(e.Graphics);
        }
    }

    private void HighlightControl(Graphics graphics)
    {
        ControlPaint.DrawBorder(
                graphics,
                this.ClientRectangle,
                Properties.Settings.Default.RequiredFieldColor,
                Properties.Settings.Default.BorderWidth,
                Properties.Settings.Default.BorderStyle,
                Properties.Settings.Default.RequiredFieldColor,
                Properties.Settings.Default.BorderWidth,
                Properties.Settings.Default.BorderStyle,
                Properties.Settings.Default.RequiredFieldColor,
                Properties.Settings.Default.BorderWidth,
                Properties.Settings.Default.BorderStyle,
                Properties.Settings.Default.RequiredFieldColor,
                Properties.Settings.Default.BorderWidth,
                Properties.Settings.Default.BorderStyle);
    }
}

Ответы [ 3 ]

4 голосов
/ 11 февраля 2010

Я не знаю подробностей вашего приложения, но вы можете получить свой собственный элемент управления из базового TextBox и позволить ему обрабатывать большую часть этого для вас. Некоторые мысли:

  • Присвойте ему обязательное свойство bool и некоторую внутреннюю логику для соответствующего цвета.

  • Текстовое поле должно отвечать самостоятельно события - когда текст введен, он может поступай правильно - меняй цвета или все, что подходит.

  • Предоставьте свой производный контроль с свойства, чтобы установить цвета, которые получают используется для каждого условия, то вы можете переключать их легко, когда пользователи решить, что они хотят розовый, а не зеленый.

  • Вы можете использовать события фокуса, чтобы «узнать», имеет ли ваш TextBox (это тот элемент управления, который вы упомянули, так что я предполагаю, что это основной элемент управления, используемый здесь) фокус или потерял его, и текст изменился события могут использоваться для управления всеми изменениями цвета в элементе управления.

  • Вы, конечно, можете подключить все текстовые поля для управления Применить / OK / все кнопки к определить, должны ли кнопки быть включен, при условии, что у вас есть кнопка «Применить» или что-то вроде того, что сохраняет данные по клику. Есть несколько способов сообщить об этом. Достаточно просто перебрать элементы управления и задать их состояние.

Похоже, это будет нормально работать.
Что вы пробовали? Вы действительно не упомянули, что пытались, но это не сработало.

4 голосов
/ 11 февраля 2010

У вас проблема, TextBox, особенный. Windows Forms оставляет всю рисование собственному элементу управления EDITBOX Windows, событие Paint не возникает. Это можно исправить, установив стиль элемента управления UserPaint в true:

using System;
using System.Drawing;
using System.Windows.Forms;

class MyTextBox : TextBox {
  public MyTextBox() {
    this.SetStyle(ControlStyles.UserPaint, true);
  }
  protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    // Paint something
    //...
  }
}

Скопируйте и вставьте это в новый класс, скомпилируйте и удалите новый элемент управления из верхней части панели инструментов. Попробуйте, вы будете очень разочарованы. То, что вы видите, является результатом почти 20-летнего взлома appcompat на элементе управления, который восходит к версии Windows 2. Одно из серьезных преступлений, которые совершает EDITBOX, это рисование себя без генерации сообщения WM_PAINT. Это было очень важно, когда Windows приходилось запускать на 386SUX, поддерживая его совместимость со старыми программами, и Microsoft не могла исправить свое поведение.

Здесь нет радостных ответов, вам придется отказаться от идеи настройки границы. То, что вы можете сделать, это дать элементу управления отчетливый BackColor, когда он имеет фокус. Например:

class MyTextBox : TextBox {
  Color mBackColor;
  protected override void OnEnter(EventArgs e) {
    mBackColor = base.BackColor;
    base.BackColor = Color.AliceBlue;
    base.OnEnter(e);
  }
  protected override void OnLeave(EventArgs e) {
    base.BackColor = mBackColor;
    base.OnLeave(e);
  }
}
3 голосов
/ 11 февраля 2010

Вы можете наследовать от базовых классов управления и добавить свою собственную логику рисования. Это не будет очень дорого с точки зрения производительности, но, если ваше приложение имеет значительный размер, вам придется заменять каждый экземпляр стандарта TextBox на собственную реализацию.

...