2013-04-30 10 views
10

Qual è il modo migliore per risolvere ?Considera il controllo come ComboBox o 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; 
     } 

     // ... 
    } 
} 

Vedete è complicato sufficiente per ottenere l'AutoCompleteMode-proprietà. Si può presumere che sia garantito che io abbia o un ComboBox o un TextBox.

La mia prima idea era quella di utilizzare generico con più tipi di T, ma sembra che questo non è possibile in .NET:

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

Purtroppo entrambi i controlli non hanno una classe base comune .

Nota: Si tratta di una domanda più generale utilizzata con un esempio ridotto a icona. Nel mio caso, desidero anche accedere/manipolare altre proprietà di completamento automatico * (che anche entrambi i controlli hanno in comune).

Grazie per le idee!

+0

La proprietà Text è l'unica cosa che cerchi? – Tim

+0

No, questo doveva essere una questione più generale. Questo era solo un esempio minimizzato. Sto anche utilizzando il Completamento automatico * -proprietà.(Sto aggiungendo questo alla domanda ora) –

+0

Non hai bisogno dell'esterno, vero? Se 'controlCombobox' è nullo, non è un ComboBox, ecc. – MAV

risposta

1

Usa Type.GetType(). Devi solo inserire un string rappresentazione della vostra proprietà a.

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

Questo permette anche di impostare il valore delle vostre proprietà troppo.

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

È possibile spostarlo in un metodo di supporto per salvare il codice di riscrittura.

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

C'è anche spazio per la gestione delle eccezioni utilizzando questo metodo.

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

Sembra essere una bella soluzione anche qui. Nel mio caso questo è troppo esagerato dal momento che sto cercando di fare un rapido sviluppo. Per questo preferisco personalmente la soluzione di Badgan M. Grazie mille! –

+1

@TheWavelength è necessario prendere in considerazione la gestione delle eccezioni, questo codice è più facile da mantenere perché sappiamo se il propert esiste o meno. Con dynamic, ottiene la proprietà in fase di runtime e non c'è modo di controllare se non lo si avvolge in un try catch. L'overhead di questo non è poi così tanto :) – LukeHennerley

+0

Grazie per la spiegazione. Non avevo questo nella mia mente. –

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

Ma, viene generata un'eccezione (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) se CurrentControl non ha WhatEver proprietà

+0

Funziona bene e sembra essere la mia soluzione preferita. Grazie. –

+0

Sono contento che abbia aiutato –

+0

+1 per la leggibilità! –

1

dipende da ciò che si sta cercando di realizzare. Se sono solo interessati alla proprietà di testo, allora questo è in realtà ereditata dalla classe Control - quindi non c'è bisogno di lanciare l'oggetto. Quindi basta:

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

    ... 
} 

Se, tuttavia, si richiede logica più complicato, si dovrebbe prendere in considerazione ripensare il vostro flusso di controllo. Vorrei suggerire un modello di View/Presenter e gestire ogni evento singolarmente - l'approccio della singola responsabilità può ridurre notevolmente la complessità.

Se si assegna la visualizzazione un'interfaccia con le proprietà attese - per esempio view.FirstName, view.HouseName o view.CountrySelection: in questo modo l'implementazione (ad es. TextBox, ComboBox, ecc.) è nascosta. Quindi:

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 
} 

Spero che sia di qualche aiuto!

+1

'Control.Text' esiste solo nella libreria winforms. Questo è acually un difetto di progettazione, poiché non tutti i controlli hanno una proprietà 'Text' significativa. 'System.Windows.Controls.Control' (la versione WPF) non ha questa proprietà comune. – MartinStettner

Problemi correlati