10

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!

The Wavelength
  • 2,836
  • 2
  • 25
  • 44

3 Answers3

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

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

Bogdan M.
  • 1,128
  • 1
  • 9
  • 23
1

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 - e.g. view.FirstName, view.HouseName or view.CountrySelection - that way the implementation (i.e. 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!

Bertie
  • 733
  • 5
  • 16
  • 1
    `Control.Text` exists only in the winforms library. This is acually a design flaw, since not all controls have a meaningful `Text` property. `System.Windows.Controls.Control` (the WPF version) doesn't have this common property. – MartinStettner Apr 30 '13 at 07:59
1

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
}
LukeHennerley
  • 6,344
  • 1
  • 32
  • 50
  • Seems to be a nice solution here which works too. In my case this is too much overhad since I'm trying to do rapid development. Because of this I personally prefer Badgan M.'s solution. Thanks a ton anyway! – The Wavelength Apr 30 '13 at 08:09
  • 1
    @TheWavelength you need to consider exception management, this code is easier to maintain because we know whether or not the propert exists. With dynamic, it gets the property at runtime and there is no way to check unless you wrap it in a try catch. The overhead of this really isn't that much :) – LukeHennerley Apr 30 '13 at 08:10
  • @TheWavelength if the understanding of this is what you are struggling on, I can explain further :) – LukeHennerley Apr 30 '13 at 08:13
  • Well, you're right. It is even "faster" (in meaning of typing the code) to use your solution because I can miss the try-catch-block. Thanks! No explanation needed, I think I've got it ;) – The Wavelength Apr 30 '13 at 08:17