我想定义一种特殊的按钮,它只允许两种可能的标签:“ON”和“OFF”。我决定继承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"!
OO世界的一般想法是在这种情况下使用Composition而不是继承。
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.
...
}
但是为了使Button“生活”在一个表单上,它必须从一些特殊的类继承。我看过Control,但似乎已经定义了Text属性。我想理想的情况是继承某些甚至没有定义Text属性的类,但是它有可用的位置,大小等属性。层次结构中的上层,在Control之后,我们有Component,但它看起来像一个非常原始的类。
有关如何实现这一目标的任何线索?我知道这是一篇很长的帖子:(
由于
答案 0 :(得分:2)
您是否考虑过按照描述的方式使用Control但不使用Control的Text属性来设置Button的Text属性?
许多Windows控件具有不在任何地方使用的Text属性。
答案 1 :(得分:1)
您可以从设计器中隐藏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";
}
}
}
答案 2 :(得分:1)
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);
}
}
}
你不能在这里使用继承,因为从OOP原则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
}
}
...
}
希望这有帮助!