Обработать управление как ComboBox или TextBox
Каков наилучший способ решить следующую проблему?
foreach (Control control in this.Controls)
{
if (control is ComboBox || control is TextBox)
{
ComboBox controlCombobox = control as ComboBox;
TextBox controlTextbox = control as TextBox;
AutoCompleteMode value = AutoCompleteMode.None;
if (controlCombobox != null)
{
value = controlCombobox.AutoCompleteMode;
}
else if (controlTextbox != null)
{
value = controlTextbox.AutoCompleteMode;
}
// ...
}
}
Вы видите, что это достаточно сложно, чтобы получить свойство AutoCompleteMode. Вы можете предположить, что у меня есть либо ComboBox, либо TextBox.
Моя первая идея заключалась в том, чтобы использовать generic с несколькими типами для T, но кажется, что это невозможно в .NET:
public string GetAutoCompleteModeProperty<T>(T control) where T: ComboBox, TextBox // this does not work, of course
К сожалению, оба элемента управления не имеют общего базового класса.
Примечание. Это будет более общий вопрос, используемый с минимизированным примером. В моем случае я также хочу получить доступ к другим функциям AutoComplete * -proprties/которые также имеют общие элементы управления.
Спасибо за идеи!
Ответы
Ответ 1
Используйте Type.GetType()
. Вам просто нужно ввести представление string
вашего свойства.
if (sender is ComboBox || sender is TextBox)
{
var type = Type.GetType(sender.GetType().AssemblyQualifiedName, false, true);
var textValue = type.GetProperty("Text").GetValue(sender, null);
}
Это также позволяет вам установить значение ваших свойств.
type.GetProperty("Text").SetValue(sender, "This is a test", null);
Вы можете перенести это на вспомогательный метод, чтобы сохранить код перезаписи.
public void SetProperty(Type t, object sender, string property, object value)
{
t.GetProperty(property).SetValue(sender, value, null);
}
public object GetPropertyValue(Type t, object sender, string property)
{
t.GetProperty(property).GetValue(sender, null);
}
Существует также место для обработки исключений, используя этот метод.
var property = t.GetProperty("AutoCompleteMode");
if (property == null)
{
//Do whatever you need to do
}
Ответ 2
dynamic currentControl = control;
string text = currentControl.WhatEver;
Но он выдает исключение (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException), если currentControl не имеет свойства WhatEver
Ответ 3
В зависимости от того, чего вы пытаетесь достичь. Если вас интересует только свойство text, это фактически унаследовано от класса Control, поэтому вам не нужно объект. Вам просто нужно:
foreach (var control in this.Controls)
{
value = control.Text;
...
}
Если вам требуется более сложная логика, вам следует подумать о переосмыслении потока управления. Я бы предложил модель View/Presenter и обрабатывал каждое событие индивидуально - подход единой ответственности может значительно уменьшить сложность.
Если вы назначаете свой вид интерфейсу с ожидаемыми свойствами - например, view.FirstName, view.HouseName или view.CountrySelection - таким образом скрыта реализация (т.е. TextBox, ComboBox и т.д.). Итак:
public interface IMyView
{
string FirstName { get; }
string HouseName { get;}
string CountrySelection { get; }
}
public class MyView : Form, IMyView
{
public string FirstName { get { return this.FirstName.Text; } } // Textbox
public string HouseName { get { return this.HouseName.Text; } } // Textbox
public string CountrySelection { get { return this.CountryList.Text; } // Combobox
}
Я надеюсь, что это поможет!