Рассматривать элемент управления как 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

к сожалению, оба элемента управления не имеют общей базы класс.

Примечание: это должен быть более общий вопрос, используемый с минимизированным примером. В моем случае я также хочу получить доступ / манипулировать другими автозаполнением* - proprties (которые также имеют общие элементы управления).

Спасибо за идеи!

3 ответов


использовать 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
}

dynamic currentControl =  control;
string text = currentControl.WhatEver;

но он создает исключение (Microsoft.Используется CSharp.Рантимебиндер.RuntimeBinderException), если currentControl не имеет какого-либо свойства


зависит от того, чего вы пытаетесь достичь. Если вас интересует только свойство text, то это фактически наследуется от управления class-поэтому вам не нужно бросать объект. Так что вам просто нужно :

foreach (var control in this.Controls)
{
    value = control.Text;

    ...
}

Если, однако, вам требуется более сложная логика, вы должны рассмотреть возможность переосмысления потока управления. Я бы предложил модель представления / презентатора и обрабатывал каждое событие индивидуально-подход одиночной ответственности может значительно уменьшите сложность.

Если вы назначаете вашему виду интерфейс с ожидаемыми свойствами-например, вид.Имя, вид.HouseName или посмотреть.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
}

Я надеюсь, что это какой-то помощи!