2013-04-30 17 views
10

Jaki jest najlepszy sposób, aby rozwiązać następujący problem?Kontrola leczenia jako ComboBox lub 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; 
     } 

     // ... 
    } 
} 

Widzisz, że jest to wystarczająco skomplikowane, aby uzyskać właściwość AutoCompleteMode. Możesz założyć, że mam gwarancję, że mam ComboBox lub TextBox.

Moim pierwszym pomysłem było użycie generic z wieloma rodzajami dla T, ale wydaje się, że nie jest to możliwe w .NET:

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

Niestety obie Kontrolą nie mają wspólną klasę bazową .

Uwaga: Jest to ogólne pytanie używane w przypadku zminimalizowanego przykładu. W moim przypadku chcę również uzyskać dostęp do innych funkcji autouzupełniania * lub manipulować nimi (które również mają wspólną kontrolę).

Dzięki za pomysły!

+0

Czy właściwość Tekst to jedyna rzecz, której szukasz? – Tim

+0

Nie, to miało być bardziej ogólne pytanie. To był tylko zminimalizowany przykład. Używam również właściwości AutoComplete *.(Dodaję to teraz do pytania) –

+0

Nie potrzebujesz zewnętrznej, jeśli nie? Jeśli "controlCombobox" ma wartość null, to nie jest to ComboBox itd. – MAV

Odpowiedz

1

Użyj Type.GetType(). Po prostu trzeba wejściu string reprezentację swojej własności.

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

ta pozwala również ustawić wartość właściwościach zbyt.

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

Możesz przenieść to do metody pomocnika, aby zapisać przepisanie kodu.

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

Istnieje również przestrzeń do obsługi wyjątków za pomocą tej metody.

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

Wydaje się być dobrym rozwiązaniem, które również działa. W moim przypadku jest to zbyt wiele, odkąd próbuję zrobić szybki rozwój. Z tego powodu osobiście wolę rozwiązanie Badgana M. I tak dziękuję ton! –

+1

@ Długość fali, którą należy uwzględnić w zarządzaniu wyjątkami, kod ten jest łatwiejszy w utrzymaniu, ponieważ wiemy, czy dany element istnieje, czy nie. Z dynamicznym, dostaje właściwość w czasie wykonywania i nie ma możliwości sprawdzenia, chyba że zawiniesz go w próbie złapania. Obciążenie tego naprawdę nie jest takie dużo :) – LukeHennerley

+0

Dzięki za wyjaśnienie. Nie miałem tego w głowie. –

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

Ale to zgłasza wyjątek (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException) jeżeli currentControl nie mają cokolwiek nieruchomość

+0

To działa dobrze i wydaje się być moim ulubionym rozwiązaniem. Dzięki. –

+0

Cieszę się, że pomogło –

+0

+1 dla czytelności! –

1

Zależy, co staramy się osiągnąć. Jeśli interesuje Cię tylko właściwość text, to jest ona faktycznie dziedziczona z klasy Control - dlatego nie trzeba jej rzutować. Potrzebujesz tylko:

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

    ... 
} 

Jeśli jednak potrzebujesz bardziej skomplikowanej logiki, powinieneś rozważyć ponowne przemyślenie swojego sterowania. Proponowałbym model View/Presenter i indywidualnie reagować na każde wydarzenie - podejście polegające na pojedynczej odpowiedzialności może znacznie zmniejszyć złożoność.

Jeśli widok zostanie przypisany interfejs o oczekiwanych właściwościach - np. view.FirstName, view.HouseName lub view.CountrySelection - w ten sposób implementacja (np. TextBox, ComboBox itp.) jest ukryta. A więc:

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 
} 

Mam nadzieję, że to pomoże!

+1

'Control.Text' istnieje tylko w bibliotece WinForm. Jest to w zasadzie usterka projektowa, ponieważ nie wszystkie kontrolki mają znaczącą właściwość "Tekst". 'System.Windows.Controls.Control' (wersja WPF) nie ma tej wspólnej właściwości. – MartinStettner

Powiązane problemy