Инкапсуляция Windows.Forms.Button - PullRequest
0 голосов
/ 23 апреля 2010

Я хочу определить специальный вид кнопки, которая допускает только две возможные метки: «ВКЛ» и «ВЫКЛ». Я решил унаследовать от Windows.Forms.Button, чтобы реализовать это, но теперь я не знаю, как следует применять это правило. Должен ли я просто переопределить свойство Text, как это?

public override string Text
{
    set
    {
        throw new InvalidOperationException("Invalid operation on StartStopButton!");
    }
}

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

foreach (Button button in myForm) {
    button.Text = "123";
}

они получат Исключение, если у меня будут какие-либо из моих специальных кнопок в форме, чего нельзя ожидать. Во-первых, потому что люди думают о свойствах просто как о «публичных» переменных, а не о методах, во-вторых, потому что они привыкли использовать и устанавливать все, что им нужно, для кнопок, не беспокоясь об исключениях.

Должен ли я просто заставить свойство set ничего не делать? Это также может привести к неловким результатам:

myButton.Text = "abc";
MessageBox.Show(abc); //not "abc"!

Общая идея мира ОО состоит в том, чтобы в подобных случаях использовать композицию вместо наследования.

public class MySpecialButton : <Some class from System.Windows.Forms that already knows how to draw itself on forms>

    private Button button = new Button(); //I'd just draw this button on this class
                                          //and I'd then only show the fields I consider
                                          //relevant to the outside world.
    ...
}

Но для того, чтобы кнопка "жива" в форме, она должна наследоваться от какого-то специального класса. Я посмотрел на Control, но, похоже, уже определено свойство Text. Я предполагаю, что идеальной ситуацией будет наследование от некоторого класса, у которого даже не будет определено свойство Text, но в котором будут доступны свойства position, size и т. Д. Выше в иерархии, после Control, у нас есть Component, но это выглядит как действительно необработанный класс.

Есть какие-нибудь подсказки о том, как этого добиться? Я знаю, что это был длинный пост: (

Спасибо

Ответы [ 3 ]

2 голосов
/ 23 апреля 2010

Рассматривали ли вы использование элемента управления описанным способом, но не использовали свойство Text элемента управления для установки свойства текста кнопки?

Многие элементы управления Windows имеют свойства текста, которые нигде не используются.

1 голос
/ 05 октября 2010

РЕДАКТИРОВАТЬ: я добавил фактический код для автора вопроса не совсем понял мою точку зрения. «Новый код кнопки»

namespace WindowsFormsApplication1
{
    public partial class Component1 : Component
    {
        public Component1()
        {
            InitializeComponent();
        }

        public Component1(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }
        bool bIsOn = true;
        public bool On
        {
            set 
         {
         bIsOn=value;

         if (bIsOn)
             button1.Text = "ON";
         else 
             button1.Text = "OFF";

         button1.Invalidate(); //force redrawing
        }

        }
        public void AddToForm(System.Windows.Forms.Form form)
        {
            form.Controls.Add(this.button1);
        }
    }
}

The main Form code : 

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Component1 onOffButton = new Component1();

            onOffButton.On = true;

            onOffButton.AddToForm(this);




        }
    }
}

alt text

Вы не должны использовать наследование здесь, потому что это не имеет смысла из принципов ООП POV.

Ограничение ввода свойства Text нарушает оригинальный интерфейс. Вместо этого определите свой собственный интерфейс и реализацию с помощью композиции и задайте для нее значения с помощью простого логического теста, например:

class OnOffButton : I_OnOffButton
{
     Button regularButton;
     bool bIsOn = true;
     public bool On
     {
      set 
         {
         bIsOn=value;

         bIsOn?(regularButton.Text = "ON"):(regularButton.Text = "OFF")

         regularButton.Invalidate(); //force redrawing
        }
     }
...

}

Надеюсь, это поможет!

1 голос
/ 23 апреля 2010

Вы можете скрыть свойство Text от дизайнера, а затем добавить новое свойство, которое принимает простое перечисление только с двумя значениями:

public enum MyButtonLabelValue
{
    On,
    Off
}

public class MyButton : Button
{
    [Browsable(false)]
    public override string Text
    {
        get
        {
            return base.Text;
        }
        set
        {
            // either do nothing or only accept "On" and "Off". I know you're concerned about violating the 
            // contract, but that would be preferrable to not having a public .Text property at all
        }
    }


    public MyButtonLabelValue LabelValue 
    {
        get
        {
            return Text == "On" ? MyButtonLabelValue.On : MyButtonLabelValue.Off;
        }
        set
        {
            base.Text = value == MyButtonLabelValue.On ? "On" : "Off";
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...