31

我有一个文本框和 RichTextBox 的事件处理程序。代码相同,但

在处理程序#1中,我这样做:

RichTextBox tb = (RichTextBox)sender

相应地在处理程序#2中:

TextBox tb = (TextBox)sender

这样做我可以完全操纵发送控制。我想知道的是如何根据其类型将发送对象转换为 Textbox 或 RichTextbox

sender.GetType().Name

然后在运行时创建控件并使用它。这样我只需要一个事件处理函数:更少的代码、更少的错误、更容易维护和 DRY :-)

4

10 回答 10

35

你永远不必施放。我刚开始的时候也这么想,这个“模式”是不正确的,而且不合逻辑。

你最好的选择是使用类似的东西:

if (sender is TextBox)
{
  TextBox tb = (TextBox)sender;
}
else if (sender is RichTextBox)
{
  RichTextBox rtb = (RichTextBox)sender;
}
else
{
  // etc
}
于 2009-03-11T11:22:47.667 回答
9

我知道这是一篇非常古老的帖子,但在 Framework 4 中,您可以将发件人转换为控件:

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

请注意,您只能引用所有不同控件共有的控件(即文本)。

于 2012-07-08T19:46:39.647 回答
7

而不是你可以使用的类型名称''。

如果您只想知道类型并且不需要对象引用:

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

但是,您通常确实需要该对象:C#7 有一个很好的语法,允许您测试并内联获取值:

if (sender is RichTextBox richTextBox)
{
    richTextBox.Text = "I am rich";
}
else if (sender is TextBox textBox)
{
    textBox.Text = "I am not rich";
}
于 2009-03-11T11:22:31.973 回答
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";
}
于 2009-03-11T11:22:25.513 回答
3

转换只能在编译时完成,因此您需要知道要在编译时转换为的类型。因此,在强制转换时不能使用运行时类型(由 GetType() 返回)。

如果您正在寻找的是多态性,您可以通过反射访问 Name 属性。我不会那样做只是为了能够重用事件处理程序。

如果你想要强类型,两个发送者上的公共基类或接口是唯一的方法。

于 2009-03-11T11:22:33.580 回答
3

根据您需要的属性,您可以将发件人转换为 TextBoxBase,因为 TextBox 和 RichTextBox 都继承自该子类。

于 2009-03-11T11:23:37.900 回答
1

上述代码的通用版本:

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

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

用作:

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

不完美,但很方便。

于 2013-10-08T22:51:14.773 回答
1

您还可以使用 inline-temporary 变量为您处理强制转换。

if (sender is RichTextBox tb)
{
    // ... //
} 
else if (sender is TextBox tb)
{
    // ... //
}
于 2017-07-06T20:44:28.247 回答
0

如果代码相同,你需要关心吗?我想知道是否铸造Control不会给你你需要的一切......

一个复杂的处理程序不一定比几个简单的处理程序好。无论哪种方式,如果你必须走这条路,“as”/“is”是可取的(它不依赖于字符串等):

TextBox tb = sender as TextBox;
if(tb!=null) {/* TextBox specific code */}
...
于 2009-03-11T11:22:57.760 回答
0

如果您不想重复代码,那么您可以强制转换两个控件,将常用操作重构为以 TextBoxBase 作为参数的单独方法。并且在您的事件处理程序中将控件转换为 System.Windows.Forms.TextBoxBase,因为这两个控件都派生自 TexbBoxBase 并调用该方法。

请注意,如果您需要任何这些控件的特定属性,则此重构将不起作用。

于 2009-03-11T11:29:52.347 回答