简体   繁体   中英

Treat control as either ComboBox or TextBox

What is the best way to solve the following problem ?

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

        // ...
    }
}

You see it's complicated enough to get the AutoCompleteMode-property. You can assume that it is guaranteed that I have either a ComboBox or a TextBox.

My first idea was to use generic with multiple types for T , but it seems that this is not possible in .NET:

public string GetAutoCompleteModeProperty<T>(T control) where T: ComboBox, TextBox // this does not work, of course

Sadly the both Controls don't have a common base class.

Note : This is meant to be a more general question used with a minimized example. In my case, I also want to access / manipulate other the AutoComplete*-proprties (which also both Controls have in common).

Thanks for ideas!

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

But, it throws an exception (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) if currentControl doesn't have WhatEver property

Depends on what you are trying to achieve. If you are just interested in the text property, then this is actually inherited from the Control class - therefore you don't need to cast the object. So you just need :

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

    ...
}

If, however, you require more complicated logic, you should consider rethinking your control flow. I would suggest a View / Presenter model and handle each event individually - the approach of single responsibility can greatly reduce the complexity.

If you assign your view an interface with the expected properties - eg view.FirstName, view.HouseName or view.CountrySelection - that way the implementation (ie TextBox, ComboBox etc) is hidden. So :

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
}

I hope that is of some assistance!

Use Type.GetType() . You just have to input a string representation of your property in.

if (sender is ComboBox || sender is TextBox)
{
  var type = Type.GetType(sender.GetType().AssemblyQualifiedName, false, true);
  var textValue = type.GetProperty("Text").GetValue(sender, null);
}

This also allows you to set the value of your properties too.

type.GetProperty("Text").SetValue(sender, "This is a test", null);

You could move this to a helper method to save rewriting code.

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

There is also room for exception handling by using this method.

var property = t.GetProperty("AutoCompleteMode");
if (property == null)
{
  //Do whatever you need to do
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM