2009-03-11 6 views
19

Ich habe einen Event-Handler für eine Textbox sowie für eine RichTextBox. Der Code ist identisch, aberSendeobjekt in Ereignishandler mit GetType(). Name

In Handler # 1 i tun:

RichTextBox tb = (RichTextBox)sender 

In Handler # 2 entsprechend:

TextBox tb = (TextBox)sender 

tun, so kann ich voll und ganz die Sendesteuer manipulieren. Was ich wissen möchte, ist, wie kann ich das Senden Objekt Textbox oder RichTextbox werfen nach seiner Art mit

sender.GetType().Name 

und dann die Steuerung zur Laufzeit erstellen und damit arbeiten. So kann ich ein Event-Handler-Funktion nur müssen: weniger Code, weniger Fehler, leichter zu pflegen und trocken :-)

+0

Können Sie ein Beispiel für eine polymorphe Methode oder Eigenschaft geben, die zwischen zwei solchen Typen geteilt wird? und wird dennoch nicht durch eine gemeinsame Schnittstelle ausgesetzt? – AnthonyWJones

Antwort

3

Je nach Eigenschaften, die Sie benötigen, könnten Sie werfen der Absender als TextBoxBase sowohl als TextBox als auch als RichTextBox erbt beide von dieser Unterklasse.

+0

das sieht vielversprechend aus! Ich werde es versuchen ... – tfl

+0

Hoffe es klappt (: – Kieron

4
RichTextBox textbox = sender as RichTextBox; 
if (textbox != null) 
{ 
    // do stuff as a rtb 
    textbox.Text = "I'm a rtb"; 
    return; 
} 

TextBox textbox = sender as TextBox; 
if (textbox != null) 
{ 
    // do stuff as a textbox 
    textbox.Text = "I'm a textbox"; 
} 
1

Anstatt der Typname Sie ‚ist‘ verwenden könnte, wenn man nur die wollen wissen, geben Sie ein und benötigen keine Objektreferenz.

if (sender is RichTextBox) 
{ 
    // ... 
} 
else if (sender is TextBox) 
{ 
    // ... 
} 

Edit: aber wie in einem Kommentar darauf hingewiesen, können Sie die oObject im Allgemeinen wollen: C# 7 hat eine nette Syntax, die Sie den Wert inline testen können und erhalten:

if (sender is RichTextBox richTextBox) 
{ 
    richTextBox.Text = "I am rich"; 
} 
else if (sender is TextBox textBox) 
{ 
    textBox.Text = "I am not rich"; 
} 
+0

das scheint der beste Kompromiss zu sein - danke – tfl

+1

Das ist in Ordnung, aber @Chris Vorschlag ist besser. Da du sofort etwas mit den Objekten machst, ersparst du dir eine zusätzliche Besetzung. –

3

Casting kann nur zur Kompilierzeit durchgeführt werden und daher müssen Sie die Typen kennen, auf die Sie während der Kompilierung umstellen möchten. Ein Laufzeittyp (wie von GetType() zurückgegeben) kann daher beim Casting nicht verwendet werden.

Wenn es sich um Polymorphismus handelt, nach dem Sie suchen, können Sie durch Reflektion auf die Eigenschaft Name zugreifen. Ich würde nicht auf diese Weise gehen, nur um Event-Handler wiederverwenden zu können.

Wenn Sie stark tippen möchten, ist eine gemeinsame Basisklasse oder Schnittstelle für die beiden Absender der einzige Weg.

28

Sie müssen nie werfen. Früher habe ich genauso gedacht, als ich anfing, dieses "Muster" ist falsch und nicht wirklich logisch.

Ihre beste Wette ist wie etwas zu verwenden:

if (sender is TextBox) 
{ 
    TextBox tb = (TextBox)sender; 
} 
else if (sender is RichTextBox) 
{ 
    RichTextBox rtb = (RichTextBox)sender; 
} 
else 
{ 
    // etc 
} 
+1

Sie werfen tatsächlich, sobald Sie den Typ des Objekts bestimmt haben, also müssen Sie * casten, aber dies ist definitiv der richtige Weg, da es nicht auf (langsamer) Reflexion beruht. – idmadj

0

Wenn der Code identisch ist, brauchen Sie das? Ich frage mich, ob Casting zu Control Ihnen nicht alles geben würde, was Sie brauchen ...

Ein komplexer Handler ist nicht unbedingt besser als mehrere einfache Handler. So oder so, wenn Sie haben diesen Weg zu gehen „als“/„ist“ vorzuziehen ist (es ist nicht abhängig von Strings usw.):

TextBox tb = sender as TextBox; 
if(tb!=null) {/* TextBox specific code */} 
... 
0

Wenn Sie den Code nicht wiederholen möchten, können Sie beide Steuerelemente umwandeln und die allgemeinen Aktionen in eine separate Methode umwandeln, die TextBoxBase als Argument verwendet. In Ihren Event-Handlern konvertieren Sie die Steuerelemente in System.Windows.Forms.TextBoxBase, da beide Steuerelemente von der TexbBoxBase abgeleitet sind und die Methode aufrufen.

Hinweis Wenn Sie bestimmte Eigenschaften eines dieser Steuerelemente benötigen, funktioniert dieses Refactoring nicht.

6

Ich weiß, dass dies eine sehr alte Post ist aber in 4-Framework können Sie den Absender als Steuer Stimmen:

Control cntrl = (Control)sender; 
cntrl.Text = "This is a " + sender.GetType().ToString(); 

Hinweis Sie nur in der Lage sind Kontrollen zu verweisen, die alle von den verschiedenen Kontrollen gemeinsam haben (zB Text).

0

generische Version des obigen Code:

public static void CastAndUse<T>(object item, Action<T> action) where T : class 
{ 
    T thing = item as T; 

    if (thing != null) 
    { 
     action(thing); 
    } 
} 

als:

CastAndUse(sender, new Action((foo) => foo = bar)); 

Nicht perfekt, aber praktisch.

0

Sie können auch eine inline-temporäre Variable verwenden, um die Besetzung für Sie zu übernehmen.

if (sender is RichTextBox tb) 
{ 
    // ... // 
} 
else if (sender is TextBox tb) 
{ 
    // ... // 
}