C# Switch Case probleme

roker002

Commander
Registriert
Dez. 2007
Beiträge
2.077
Mein Problem ist.... ich will zu den einzelnen Controlelementen hilfestellung schreiben. mit ToolTip Control ist es schön und gut aber ich will keine bluberblasen haben. der text wird einfach unten anzegeizt in einen Label. Das Problem ist... Ich habe den code so geschrieben dass ich über switch abfrage welcher control das ist (um nicht jedesmal ein neue event aufzumachen....

naja hier ist der Codeausschnitt

Code:
        private void HelpLink(object sender, EventArgs e)
        {
            String Help = "";
            Control c = (Control)sender;

            switch (c.Name)
            {
                case "SuchenTextBox":
                    Help = "irgendwas";
                    break;
                default: Help = ""; return;
            }
            HelpLabel.Text = Help;
        }

sobald der name des controlelementes sich geändert hat kann man den code vergessen und muss alles neue einstellen.

in den case will er keine strings annehmen die nicht statisch sind. D.h. ich kann nicht gehen und sagen
Code:
case SuchenTextBox.Name: break;

wie kann ich den sonst das problem lösen wenn ich keine dynamische strings in den case verwende kann?
 
Mit den Restriktionen musste leben, nimm einfach eine if/else Struktur und gut is...

if(sender == SuchenTextBox)
{
}
else if(sender == AndereTextBox)
{
}
else if(sender == NochNeAndereTextBox)
{
}
else
{
}
 
ist ja gemein.... schade, dann geht es halt nicht anders

danke
 
Alternativ könntest du auch in die Tag-Eigenschaft des Controls deinen Tooltip eintragen. Danach reduziert sich deine HelpLink() Methode auf folgendes:

Code:
private void HelpLink(object sender, EventArgs e)
{
  HelpLabel.Text = ((Control)sender).Tag.ToString();
}

Ggfs. solltest du noch etwas "Glue" Code hinzufügen um den Fall abzufangen, wenn die Tag Eigenschaft gleich null ist. ;)

Ebenso könntest du auch einen Extender-Provider implementieren, sodaß du automatisch für jedes Control eine HelpText Eigenschaft hast und die Tag Eigenschaft für andere Zwecke nutzen kannst. Melde dich einfach, falls es das ist was du machen willst aber nicht weisst wie es geht...
 
Zuletzt bearbeitet:
also ich kann praktisch mit TAG des controls die hilfestellung aufschreiben?

naja mit dem NULL wert ist es einfach

Code:
if((Control)sender).Tag.ToString()!=null)

mit Extender-Provider meinst du eigene Klasse für Label zu schreiben dass wie ToolTip die Sachen für mich übernimmt? Ist interesant, kann aber abwarten, da es sowieso im Feld Optimierung fällt. Zuerst muss ja alles funktionieren. Ich komme noch da drauf zurück wenn es soweit ist.
 
Zum Tag: Du kannst in der Control.Tag Eigenschaft alles Mögliche ablegen. Es ist dazu gedacht weitere Informationen für ein Control zu hosten, die nicht über andere Eigenschaften verfügbar sind. Den Hilfetext da abzulegen, wäre eine Möglichkeit diese Eigenschaft zu nutzen. Im übrigen kannst du den Hilfetext direkt im Designer im Eigenschaftenfenster der Controls festlegen. Somit ist die Info direkt am Control abgelegt und nicht in einer eigenständigen Methode. Ist von der Definition/Verwendung intuitiver und lässt deinen Code leichter pflegen...

Zum eigentlichen Glue-Code:

Code:
// Falsch:
if((Control)sender).Tag.ToString() != null)

// Richtig:
if((Control)sender).Tag != null)

Sonst wirst du eine NullReferenceException bekommen, da Tag null sein kann und du in deinem Beispiel "vermutest" das Tag eine Object-Instanz ist.

Zum Extender Provider:

Der Extender Provider ist interessant, weil man mit diesem dynamisch für jedes Control/Componente auf einer Form eine Eigenschaft definieren kann ohne extra für jedes Control/Componente eine abgeleitete Klasse erzeugen zu müssen. Ich werde mal paar Minuten so einen Provider schreiben und hier posten, dann hat jeder was davon...
 
ich merke gerade... dieser weg funktiniert nur für die einfache beschreibung. Sobald die komplexität durch andere Elemente wie z.B. ListBox Steigt kommt man nicht drum alles per hand zu machen, wenn man zum Bsp Erklärung zu den einzelnen elementen in der Liste abgeben will.

oder gibts da auch einen weg?
 
Rossibaer schrieb:
Code:
private void HelpLink(object sender, EventArgs e)
{
  HelpLabel.Text = ((Control)sender).Tag.ToString();
}

Mist, da war jemand schneller. ^^
Ist perfekt, öh hab´s jetzt aber nicht im Kopf:
Ist "Tag" nicht schon ein String?

EDIT: Hab´s gerade nachgeguckt ist ein Object, sorry. -.-
 
Zuletzt bearbeitet:
Wenn du die Klasse in dein Projekt aufnimmst, dann speichere das Projekt nach dem du die Klasse eingefügt hast und kompiliere das Projekt. Zu guter Letzt schließe Visual Studio und öffne es noch mal neu, weil z.B. mein VS 2005 irgend ein Drecks-Initialisierungsproblem hatte. Nach dem du das gemacht hast, sollte in der Toolbox ein neues Control "HelpTextLabel" aufscheinen, was du wie z.B. eine Textbox in die Form einfügen kannst. Nach dem Einfügen sollte bei jedem Control eine "HelpText auf {Irgendwas}" Eigenschaft unter "Sonstiges" im Designer Eigenschaftenfenster erscheinen. Die HelpText Eigenschaft ist vom Typ String.

Hier nun der Extender-Provider:

Code:
  // Einige Defintionen welche Type von Objekten die dynmische Eigenschaft im Designer von Visual Studio
  // erhalten sollen und wie die dynamische Eigenschaft heißen soll, entsprechend muss die Extender Klasse
  // dann die Get und Set Methode implementieren! Der Name der Methoden bildet sich aus Get bzw. Set und
  // Eigenschaftenname, z.B. wenn die Eigenschaft "HelpText" ist:
  // Get:
  // public string GetHelpText(System.Windows.Forms.Control control) { };
  // Set:
  // public void SetHelpText(System.Windows.Forms.Control control, string helptext) { };
  [System.ComponentModel.ProvideProperty("HelpText", typeof(System.Windows.Forms.Control))]
  public class HelpTextLabel : System.Windows.Forms.Label, System.ComponentModel.IExtenderProvider
  {
    // lokaler Speicher in Form einer typisierten Hashtable um die Hilfeinformationen
    // für jedes Control speichern zu können
    private System.Collections.Generic.Dictionary<System.Windows.Forms.Control, string> haHelpText;
    // Der Konstruktor der die Hashtable (Dictionary) initialisiert in dem alle Hilfeinformationen
    // für die Controls abgespeichert sind
    public HelpTextLabel()
    {
      haHelpText = new Dictionary<System.Windows.Forms.Control, string>();
    }
    // Interface-Methode des ExtenderProvider über die der Designer von Visual Studio erkennt, ob ein
    // Control zusätzlich die dynamische Eigenschaft "HelpText" hat oder nicht. Im Endeffekt wird nur der
    // Typ des in Frage kommenden Controls geprüft
    public bool CanExtend(object extendee)
    {
      return (extendee is System.Windows.Forms.Control && (!(extendee is HelpTextLabel)));
    }
    // Die Get-Methode des Extender-Providers
    // Im Designer des Visual Studio sollte für jedes Control nun unter Eigenschaften/Sonstiges eine
    // Eigenschaft "HelpText auf {HelpTextLabelName}" auftauchen, die entsprechend gesetzt werden kann
    [System.ComponentModel.DefaultValue("")]
    public string GetHelpText(System.Windows.Forms.Control control)
    {
      if (haHelpText.ContainsKey(control)) return haHelpText[control];
      return string.Empty;
    }
    // Die Set-Methode des Extender-Providers
    // Im Designer des Visual Studio sollte für jedes Control nun unter Eigenschaften/Sonstiges eine
    // Eigenschaft "HelpText auf {HelpTextLabelName}" auftauchen, die entsprechend gesetzt werden kann
    public void SetHelpText(System.Windows.Forms.Control control, string helptext)
    {
      if (helptext == null) helptext = string.Empty;
      haHelpText[control] = helptext;
      control.MouseEnter +=new EventHandler(control_MouseEnter);
      control.MouseLeave += new EventHandler(control_MouseLeave);
    }
    // Handler um das HelpTextLabel der Form zu aktualisieren, sprich den Text dynamisch anzupassen
    private void control_MouseEnter(object sender, EventArgs e)
    {
      System.Windows.Forms.Control control = ((System.Windows.Forms.Control)sender);
      this.Text = GetHelpText(control);
    }
    // Handler um das HelpTextLabel der Form zu aktualisieren, sprich den Text dynamisch anzupassen
    private void control_MouseLeave(object sender, EventArgs e)
    {
      System.Windows.Forms.Control control = ((System.Windows.Forms.Control)sender);
      this.Text = string.Empty;
    }
    // Überschreibe die Text Eigenschaft, sodaß diese nicht mehr im Designer vom Visual Studio auftaucht.
    // Die Text Eigenschaft wird eh vom Provider dynamisch gesetzt und mögliche Änderungen über den Designer sind
    // sinnlos.
    [System.ComponentModel.Browsable(false)]
    public override string Text
    {
      get { return base.Text; }
      set { base.Text = value; }
    }
  }

Viel Erfolg!

EDIT: Habe noch mal die Attribute von Text Eigenschaft in der Klasse geändert!

EDIT 2: Ist die Liste deiner ListBox hart codiert oder wird sie dynamisch gefüllt?
 
Zuletzt bearbeitet:
sieht schon cool aus! die ganzen eigenschaften von Label bleiben erhalten und nur die neuen kommen dazu. Ich dachte es wäre mehr arbeit, deswegen wollte ich es später machen aber ich sehe es jetzt dass es ehe lohnt als sonst. mit den Tag.

erscheint dieser Label aus im Toolbox? ALT+STRG+X ... <--- dieser ToolBox

edit:
wie finde ich das heraus?

edit2: muss man diese Komponente als eigenes Projekt aufbauen oder kann man diesen Control zu dem bestehenden Projekt hinzufügen. Ich habe das zweitere.... asoooo da in der kleine ECKE... man man... ist sowas von unübersichtlich
 
Zuletzt bearbeitet:
Normalerweise taucht HelpTextLabel in der Toolbox auf sobald du das Visual Studio Projekt nach dem Kompilieren neu öffnest. Wie gesagt ich habe hier bei VS 2005 ein Initialisierungsproblem. Aber alternativ kannst du das auch zur Toolbox manuell hinzufügen. Zeige die Toolbox an und gehe über das Kontextmenü auf "Element hinzufügen ..." Die restlichen Schritte sind ähnlich wie bei den Verweisen...

Ich habe das mal in mein Projekt IRadioStreamRecorder eingebaut, in der Toolbox gibt es eine Sektion "IRadioStreamRecorder Komponenten" unter der ich dann das HelpTextLabel finde. Du kannst ja mal bei dir in deinem Projekt schauen ob es da auch eine Sektion "ProjektName Komponenten" gibt.
 
Zuletzt bearbeitet:
kann man mit dem element nicht auf sich selbst hilfestellung machen? Es ist ja ein sichtbarer Feld auf dem Dialogfenster.
 
Doch, das würde natürlich auch gehen, es stellt sich halt nur die Frage nach dem Sinn dahinter.
Im Code von Rossibaer wird durch folgenden Teil verhindert, dass der ExtensionProvider ein Control vom Typ HelpTextLabel erweitern kann. (der rote Teil)
Code:
public bool CanExtend(object extendee)
{
    return (extendee is System.Windows.Forms.Control && [COLOR="Red"](!(extendee is HelpTextLabel))[/COLOR]);
}
Wenn du das Rote löschst, kann auch für ein HelpTextLabel selbst ein Hilfetext angezeigt werden.


@Rossibaer
Dank für den Code, hab mich vorher noch nie mit dem ExtensionProvider befasst, aber dank deinem Beispiel hab ich gemerkt, dass es einfacher ist als ich dachte.
Das kann ich bestimmt mal gebrauchen. :)
 
Wie Grantig bereits richtig bemerkte kann man auch den Extension Provider für das HelpTextLabel selbst erweitern, einfach nur die rote Bedingung entfernen. Das schöne am Extension Provider ist nunmal das er für jedes Objekt genutzt werden kann (einfach die CanExtent() Methode entsprechend anpassen) ohne das man mühselig für jedes Element eine abgeleitete Klasse schreiben muss.

Im übrigen habe ich auf die Art nen schönen Localizer geschrieben mit dem jedes Element auf einer Maske in der entsprechenden Landessprache "on the fly" lokalisiert werden kann. Das ganze basiert auf den lokalisierten Ressourcen der Form und eben einem Extension Provider.

@Grantig: Nix zu Danken! Die Theorie dahinter ist in der MSDN sehr gut beschrieben und das Beispiel von mir ist nur eine verkürzte Version dessen was MS zur Verfügung stellte... ;)

@Roker:
edit: wie finde ich das heraus?
schon etwas älter die Frage, ab was willst du herausfinden?
 
Zuletzt bearbeitet:
ja hat sich alles schon geklärt! Danke


EDIT:
ich habe die Erweiterung für den ErrorProvider geschrieben.... so kann man zum BSP den min Länge des Textes setzen oder auf die Zeichengruppe überprüfen! Alphabetics/Nummeric/gemischt

Code:
[System.ComponentModel.ProvideProperty("ExtError", typeof(System.Windows.Forms.Control))]
[System.ComponentModel.ProvideProperty("MinLen", typeof(System.Windows.Forms.Control))]
[System.ComponentModel.ProvideProperty("IsAlphabetics", typeof(System.Windows.Forms.Control))]
public partial class ExtErrorProvieder : System.Windows.Forms.ErrorProvider, IExtenderProvider
{
    private System.Collections.Generic.Dictionary<System.Windows.Forms.Control, string> ErrorText;
    private System.Collections.Generic.Dictionary<System.Windows.Forms.Control, int> MinLen;
    /// <summary>
    /// 0: Nur Nummerische Werte
    /// 1: Nur Alphabetische Werte
    /// 2: Gemischte Werte
    /// </summary>
    private System.Collections.Generic.Dictionary<System.Windows.Forms.Control, int> IsAlphabetic;
    /// <summary>
    /// Generiert einen ErrorProvider mit zusätzlichen funktionen wie, min Länge, Überprüfung auf Alphabetics/Nummerics
    /// </summary>
    public ExtErrorProvieder()
    {
        ErrorText = new Dictionary<System.Windows.Forms.Control, string>();
        MinLen = new Dictionary<Control,int>();
        IsAlphabetic = new Dictionary<Control, int>();
    }
    [System.ComponentModel.DefaultValue("")]
    public String GetExtError(System.Windows.Forms.Control c)
    {
        if (ErrorText.ContainsKey(c)) return ErrorText[c];
        return String.Empty;
    }
    public void SetExtError(System.Windows.Forms.Control c, String error)
    {
        if (ErrorText != null)
        {
            ErrorText[c] = error;
            c.Validated += new EventHandler(TextValidated);
        }
    }
    [System.ComponentModel.DefaultValue(0)]
    public int GetMinLen(System.Windows.Forms.Control c)
    {
        if (MinLen.ContainsKey(c)) return MinLen[c];
        return 0;
    }
    public void SetMinLen(System.Windows.Forms.Control c, int len)
    {
        if (MinLen != null)
            MinLen[c] = len;
    }
    public int GetIsAlphabetics(System.Windows.Forms.Control c)
    {
        if (IsAlphabetic.ContainsKey(c)) return IsAlphabetic[c];
        return 2;
    }
    public void SetIsAlphabetics(System.Windows.Forms.Control c, int value)
    {
        if (IsAlphabetic != null)
            IsAlphabetic[c] = value;
    }
    public void TextValidated(Object sender, EventArgs e)
    {
        if (ErrorText == null || MinLen == null || IsAlphabetic == null)
            return;
        if (ErrorText.ContainsKey((Control)sender) && MinLen.ContainsKey((Control)sender) && IsAlphabetic.ContainsKey((Control)sender))
        {
            Control c = (Control)sender;
            ///Überprüfe die Länge des Textes.
            if (c.Text.Length < MinLen[c])
            {
                base.SetError(c, ErrorText[c]);
                return;
            }
            ///Überprüfe ob welche Werte im Text erlaubt sind.
            switch (IsAlphabetic[c])
            {
                case 0:
                    if (MkdServices.library.ContainsAlphabetics(c.Text))
                    {
                        base.SetError(c, ErrorText[c]);
                    }
                    else
                    {
                        base.SetError(c, string.Empty);
                    }
                    break;
                case 1:
                    if (MkdServices.library.ContainsNummeric(c.Text))
                    {
                        base.SetError(c, ErrorText[c]);
                    }
                    else
                    {
                        base.SetError(c, string.Empty);
                    }
                    break;
                case 2:
                    ///Beide Werte sind erlaubt, wird also egal sein was drinne steht
                    break;
                default:
                    break;
            }
        }
    }
}

ja ich weiss ist bissel schlecht programmiert aber es tuts... wenn man mag kann man auch das Teil optimieren!

Die Errors werden erst dann ausgegeben wenn die Längebeschränkung oder auch überprüfung der chars anschlägt.

EDIT2: Wow durch diese Programmierung habe ich in meinen Sourcecode über 300 Zeilen gesparrt und dazu viele Schleifen umgangen (für die überprüfung der Eigabefelder)

EDIT3: Eine Letzt Frage... wie kann ich kommentare für die Komponenten erstellen lassen? Sieh bildchen... Wie kann man einen Dropdownfensterchen machen (auch am Bild) und die Vorgaben erstellen?
 

Anhänge

  • Unbenannt.jpg
    Unbenannt.jpg
    106,3 KB · Aufrufe: 118
Zuletzt bearbeitet:
Servus Roker,
mein Gott, da hab ich dir ja was gezeigt :D

Zu deinen Fragen: Beschreibung, Kategorie, DefaultValue und Editor lassen sich über die Attribute der Get-Methode steuern:

z.B.:
Code:
[System.ComponentModel.DefaultValue(""),
System.ComponentModel.Description("Erweiterte Fehlerbehandlung"),
System.ComponentModel.Category("Behavior"),
System.ComponentModel.Editor(typeof(ExtErrorEditor), typeof(System.Drawing.Design.UITypeEditor)]
public String GetExtError(System.Windows.Forms.Control c)
{
  if (ErrorText.ContainsKey(c)) return ErrorText[c];
  return String.Empty;
}

// Erzwingt das Serialisieren der Extender Eigenschaft in der Form.InitializeComponent() Methode
// Wenn das DefaultValue Attribut gesetzt ist sollte er das dann da ebenfalls "Vordefinieren"
public bool ShouldSerializeExtError(System.ComponentModel.Component component)
{
   return true;
}

Der Editor muss natürlich auch erstellt werden, z.B.:
Code:
  public class ExtErrorEditor : System.Drawing.Design.UITypeEditor
  {
    public ExtErrorEditor()
      : base()
    {
    }

    public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
    {
      return System.Drawing.Design.UITypeEditorEditStyle.DropDown;
    }

    public override bool IsDropDownResizable
    {
      get { return true; }
    }

    public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
      System.Windows.Forms.Design.IWindowsFormsEditorService edSvc =
        (System.Windows.Forms.Design.IWindowsFormsEditorService)provider.GetService(
        typeof(System.Windows.Forms.Design.IWindowsFormsEditorService));
      if (edSvc != null)
      {
        System.Windows.Forms.ListBox lbValues = new System.Windows.Forms.ListBox();
        lbValues.Size = new System.Drawing.Size(150, 200);
        lbValues.Items.Add("Hello");
        lbValues.Items.Add("world");
        lbValues.Items.Add("!");
        lbValues.Tag = edSvc;
        lbValues.SelectedIndexChanged += new EventHandler(lbValues_SelectedIndexChanged);
        edSvc.DropDownControl(lbValues);
        return lbValues.SelectedItem as string;
      }
      return value;
    }

    void lbValues_SelectedIndexChanged(object sender, EventArgs e)
    {
      System.Windows.Forms.ListBox lbValues = (System.Windows.Forms.ListBox)sender;
      System.Windows.Forms.Design.IWindowsFormsEditorService edSvc = (System.Windows.Forms.Design.IWindowsFormsEditorService)lbValues.Tag;
      edSvc.CloseDropDown();
    }
  }

Neu kompilieren vor dem ersten Einsatz nicht vergessen. Hoffe das war das was du gesucht hast...
 
Zuletzt bearbeitet:
Was genau bewirkt das Serialisieren? ich verstehe in diesen zusammenhand nicht wirklich was jetzt in InitializeComponent passiert.

Wie macht man einen Dropdown ohne einen Listbox? ich habe jetzt versucht umzubauen aber es klappt nciht so richtig.

hey ich habe kleines Tutorium zu dem Thema gefunden... najut, wenn du Zeit hast wäre es auch super die Lösung von dir (@rossibär) zu bekommen.

Tutorium
 
Zum Serialisieren allgemein:
Sobald du ein Control auf die Form packst, dann springt ein Serializer des .Net Frameworks an und schreibt automatisch ein paar Sachen in die InitializeComponent Methode der Form. Ab Visual Studio 2005 ist dieser Code in der Form.Designer.cs Datei. Dieser Code macht nichts weiter als dein Control zu initialisieren, d.h. es werden verschiedene Eigensachaften wie der Name, Size, Location des Controls gesetzt. Ebenso wird das Control zur Auflistung von Form.Controls hinzugefügt. Das macht dieser Serializer.

Wenn du jetzt für deinen Extender die ShouldSerializeExtendedPropertyName() mit "return true;" definiert hast, dann wird erzwungen, das der Serializer den Wert der Eigenschaft für jedes Control immer in der InitializeComponent() Methode reinschreibt. Das ist im Übrigen nicht immer der Fall, wenn du z.B. das DefaultValue Attribute an der Get-Methode festlegst. Die Defaultwerte werden dann nicht serialisiert, weil es eben Defaultwerte sind.

In der InitializeComponent() Methode wirst du zu deinem Extender für die Controls sicher folgenden Eintrag finden:
Code:
this.ExtenderName.SetPropertyName(this.ControlName, PropertyValue);

ein konkretes Beispiel aus meinen Projekt:
Code:
this.localizer.SetLocalizedItem(this.pbFileNew, "pbFileNew");

Hoffe das ist jetzt etwas klarer...

DropDown:
Ich verstehe gerade nicht was du meinst. Also das Dropdown Control kann alles mögliche sein. Ich habe da mal eine Listbox reingepackt, weil es am einfachsten ist. Schreib mal genau was du haben willst, also nur DropDown ist ein bissel wenig...
 
ups.. ich meinte einen TextBox als Dropdown. Es ist bei den längeren Text sehr unübersichtlich wenn man lange Texte schreiben will (wie z.B. die Fehlerbeschreibung).
 
Zuletzt bearbeitet:
Dann setze doch das Editor-Attribute der Get-Methode auf MultilineStringEditor
Code:
[Editor(typeof(System.ComponentModel.Design.MultilineStringEditor), typeof(UITypeEditor))]
public string GetExtError(System.Windows.Forms.Control control)
{
}
falls es das ist was du meinst. Dabei musst du aber die System.Design.dll zu den Projektverweisen hinzufügen.

Alternativ kann man auch die String-Variante des Editor Attributes nehmen, dann muss da aber der vollständige Name des Typs (die Langform) angegeben werden. Auf diese Art sparst du dir aber so den Verweis auf System.Design.dll.
Code:
[Editor("System.ComponentModel.Design.MultilineStringEditor ...", typeof(UITypeEditor))]
public string GetExtError(System.Windows.Forms.Control control)
{
}
 
Zuletzt bearbeitet:
Zurück
Oben