2010-04-23 6 views
0

Je souhaite définir un type spécial de bouton qui n'autorise que deux libellés possibles: "ON" et "OFF". J'ai décidé d'hériter d'un Windows.Forms.Button pour l'implémenter mais maintenant je ne sais pas comment appliquer cette règle. Dois-je juste remplacer la propriété Text comme ça?Encapsulation d'un Windows.Forms.Button

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

Le problème que je vois avec ceci est que je brise le contrat que tous les boutons devraient avoir. Si un code essaie quelque chose comme

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

ils auront une exception si j'ai un de mes boutons spéciaux sur la forme, ce qui est quelque chose qui ne expectable. Tout d'abord, parce que les gens considèrent les propriétés comme des variables «publiques», et non comme des méthodes, parce qu'elles sont habituées à utiliser et à définir ce qu'elles veulent sur les boutons sans avoir à se soucier des exceptions.

Devrais-je simplement faire en sorte que la propriété set ne fasse rien? Cela pourrait conduire à des résultats difficiles:

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

L'idée générale du monde OO est dans ce genre de cas utiliser la composition au lieu de l'héritage. Mais pour que le bouton "vive" sur un formulaire, il doit hériter d'une classe spéciale. J'ai regardé Control, mais il semble que la propriété Text soit déjà définie. Je suppose que la situation idéale serait d'hériter d'une sorte de classe qui n'aurait même pas la propriété Text définie, mais qui aurait des propriétés de position, de taille, etc. En haut de la hiérarchie, après le contrôle, nous avons Component, mais cela ressemble à une classe vraiment brute.

Des indices sur la façon d'y parvenir? Je sais que ce fut un long message :(

Merci

Répondre

1

Vous pouvez cacher la propriété Text du concepteur, puis ajouter une nouvelle propriété qui prend une simple énumération avec seulement deux valeurs:

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"; 
     } 
    } 
} 
+0

Cela ne semble pas être une bonne idée. Vous devez toujours remplacer le mutateur de Text et le faire ne rien faire. –

+0

True. Mais quand j'y ai réfléchi pendant un moment, je ne pensais pas que cela risquait de poser un problème, car toute personne qui utilise votre butin personnalisé saura exactement ce qu'elle fait et ne voudra pas que le texte soit autre chose que Allumé ou éteint. –

2

Avez-vous envisagé d'utiliser Control de la façon que vous avez décrite mais sans utiliser la propriété Text du contrôle pour définir la propriété Text du bouton?

Beaucoup de contrôles Windows ont des propriétés de texte qui ne sont utilisées nulle part

+0

N'a pas pensé à ça. S'il n'y a pas de meilleure solution c'est ce que je ferai. –

1

EDIT: J'ai ajouté le code réel pour l'expéditeur de la question n'a pas tout à fait comprendre mon point. Le « Nouveau code bouton »

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

Vous ne devez pas utiliser ici l'héritage, car il n'y aurait aucun sens des principes POO POV. Limitation de la saisie d'une propriété de texte enfreint l'interface d'origine.

Au lieu de cela, définir votre propre interface et mise en œuvre par l'utilisation de la composition, et l'ont mis des valeurs par simple test booléen, comme ceci:

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

} 

Hope this helps!

+0

Ce n'est pas le cas. Je pense qu'il vous manque tout le point du thread: pour afficher un bouton sur un formulaire, vous devez soit hériter d'un bouton ou d'un composant, et dans les deux cas vous allez devoir violer le contrat de propriété Text. –

+0

Etes-vous sûr que je suis celui qui manque le point ici? Pensez-vous réellement qu'il est impossible d'ajouter l'objet membre regularButton (qui est System.Windows.Forms.Button) à un formulaire? Franchement, vous devriez d'abord relire mon extrait de code, car votre commentaire ne semble pas refléter une compréhension complète. – Jas

+0

Je dois manquer quelque chose, car je ne vois pas comment vous pouvez mettre une instance d'une classe qui n'implémente pas un contrôle dans un formulaire, en premier lieu .. –

Questions connexes