Frage

Ich habe einen Event-Handler für eine Textbox sowie für eine RichTextBox. Der Code ist identisch, aber

In Handler # 1 i tun:

RichTextBox tb = (RichTextBox)sender

In Handler # 2 entsprechend:

TextBox tb = (TextBox)sender

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

sender.GetType().Name

und erstellen Sie dann das Steuerelement zur Laufzeit und mit ihr arbeiten. So kann ich eine Event-Handler-Funktion nur müssen: weniger Code, weniger Fehler, leichter zu pflegen und trocken: -)

War es hilfreich?

Lösung

Je nachdem, welche Eigenschaften Sie benötigen, können Sie den Absender als TextBoxBase, da sowohl die TextBox und RichTextBox beide von dieser Unterklasse erben werfen könnte.

Andere Tipps

Sie haben nie gegossen. Ich benutzen die gleiche Art und Weise zu denken, als ich anfing, das ‚Muster‘ ist falsch, und nicht wirklich logisch.

Am besten ist es, etwas zu verwenden wie:

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

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

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

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

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

Gießen kann nur bei der Kompilierung-Zeit durchgeführt werden und somit müssen Sie die Typen kennen, die Sie bei der Kompilierung-Zeit werfen möchten. Eine Runtime-Typ (wie er von GetType ()) kann daher nicht verwendet werden beim Gießen.

Wenn es Polymorphismus Sie suchen Sie die Eigenschaft Name durch Reflexion zugreifen konnte. Ich würde diesen Weg nicht gehen, obwohl nur in der Lage sein, Event-Handler wieder zu verwenden.

Wenn Sie starke Typisierung wollen, eine gemeinsame Basisklasse oder Schnittstelle auf den beiden Sendern ist der einzige Weg zu gehen.

Anstatt den Typennamen könnten Sie ‚ wird ‘.

Wenn Sie nur die Art kennen und nicht eine Objektreferenz benötigen:

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

Jedoch Sie in der Regel das Objekt 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";
}

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

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

Wenn der Code identisch ist, müssen Sie kümmern? Ich frage mich, ob zu Control Gießen würden Sie nicht alles, was Sie brauchen ...

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

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

Wenn Sie nicht wollen, um den Code zu wiederholen, dann können Sie sowohl die Kontrollen werfen, Refactoring, die gemeinsame Aktionen zu einem separaten Verfahren, das TextBoxBase als Argument. Und in Ihrem Event-Handler, die Kontrollen zu System.Windows.Forms.TextBoxBase konvertieren, da beide Steuerelemente aus dem TexbBoxBase abgeleitet sind und die Methode aufrufen.

Bitte beachten Wenn Sie bestimmen Eigenschaften von jedem dieser Kontrollen müssen dann dieses Refactoring nicht funktionieren.

Allg 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);
    }
}

Wird als:

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

Nicht perfekt, aber praktisch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top