Я пытаюсь сделать функцию, которая возвращает фактический элемент управления. Я знаю, что вы можете это сделать, когда знаете тип объекта:
public static Control GetCtl(this object obj)
{
//(obj as obj.GetType()) ?
return (TextBox)obj;
}
Но что, если мне нужно получить один из другого (неизвестного) типа объекта, например TextBox или RichTextBox? Затем я буду использовать это:
private void TextBox1_Click(object sender, EventArgs e)
{
sender.GetCtl().Select(0, 0);
}
Хотя TextBox
и RichTextBox
похоже, имеют один и тот же метод Select
, когда я пробовал вышеупомянутую GetCtl()
, она всегда GetCtl()
ошибку. Как это сделать правильно?
Изменить: поскольку вы не можете получить доступ к "завершенному" свойству управления как sender
во всех собственных процедурах/методах (т.е. _Click()
, _MouseMove()
) Я хочу создать функцию, которая может вернуть фактический элемент управления, а не уверен, как объяснить это лучше, но вот как я буду использовать его:
Private void SomeControl_KeyDown(object sender, KeyEventArgs e){
sender.getCtl(). //<-- so I can access anything here
(sender as Button).Text = "sometext" // <-- so I won't have to do this
//I wish the following would work. But you get the idea
(sender.GetType())sender.Text = "";
//or...
(sender as sender.GetType()).Text = "";
}
RichTextBox
и TextBox
оба являются производными от TextBoxBase.
Чтобы сообщить компилятору, что вы хотите рассматривать объект как определенный тип, вы можете выполнить операцию литья. В этом случае вам нужно sender
в TextBoxBase
а затем вы можете получить доступ к методу Select():
private void TextBox1_Click(object sender, EventArgs e)
{
var textbox = sender as TextBoxBase;
if (textbox != null)
textbox.Select(0, 0);
}
Это использует ключевое слово as, чтобы TextBoxBase
объект sender
TextBoxBase
. Обратите внимание, что вы не можете просто что-то приложить к чему-либо еще. Фактически объект должен быть экземпляром того типа, который вы используете. Если sender
не является экземпляром чего-то, полученного из TextBoxBase
, операция cast вернет значение null.
Как правило, обработчики событий winforms должны подниматься только в очень контролируемых и известных обстоятельствах - вы должны быть очень уверены в том, что это событие поднимается с помощью элемента управления, полученного из TextBoxBase. Там не так много смысла поднимать его от всего остального.
Если вам действительно нужен метод преобразования отправителя в TextBoxBase, вы можете написать его как:
private TextBoxBase ToTextBoxBase(object sender)
{
var textbox = sender as TextBoxBase;
if (textbox == null)
throw new Exception("The given object is not derived from TextBoxBase");
return textbox;
}
Вы бы использовали его как:
ToTextBoxBase(sender).Select(0, 0);
Если отправитель не является TextBoxBase, этот вызов будет генерировать исключение "данный объект не является производным от TextBoxBase".
Важно понять, что вы работаете с строго типизированным языком. Если вы попытаетесь вызвать метод объекта, который не относится к типу, содержащему этот метод, программа даже не будет компилироваться (если только этот тип не является dynamic
, но это другое обсуждение).
Можно создать метод, который вы можете вызвать с помощью этого синтаксиса:
sender.ToTextBoxBase()
Это называется методом расширения. Тем не менее, вы бы расширяли класс System.Object
для очень конкретной цели, что не рекомендуется.
getCtl()
? Потому что я хочу также использовать его на других элементах управления, чтобы легко получить доступ к методамsender
.null
? Это означает, что это неTextBoxBase
а что-то еще