Announcement

Collapse
No announcement yet.

PropertyGrid und dynamische Aufzählung aus DB

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • PropertyGrid und dynamische Aufzählung aus DB

    Wir benutzen ein PropertyGrid um Benutzereinstellungen einer Anwendung zu speichern und zu verändern.Mit Werten, die reinen Text oder Zahlen darstellen, ist dies auch kein Problem.

    Nun möchten wir aber eine Eigenschaft, nennen wir sie mal "Hersteller", mit einem Wert füllen, der die ID des Herstellers darstellt, aber in dem PG soll der Name des Herstellers stehen. Die Liste der Hersteller muss dazu dynamisch aus der DB gelesen werden.

    Folgenden Lösungsansatz habe ich bis jetzt schon umgesetzt:
    [highlight=vbnet]
    Public Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValues Collection
    Dim _Values As New Collections.SortedList

    If _dtVendors.Rows.Count > 0 Then
    For Each _rowVendors In _dtVendors.Rows
    _Values.Add(_rowVendors.VendorsGUID, _rowVendors.VendorsName)
    Next
    End If

    Return _Values

    End Function
    [/highlight]
    Doch dann frag ich mich, wie es weiter gehen soll. Wie kann ich nun aus der SortedList (VendorsGUID, VendorsName) nun die benötigte StandardValueCollection erstellen?

    Wie müsste ich dann weiter vorgehen, um nicht die VendorsGUID zu "sehen", sondern der Eintrag VendorsName und dass der Wert "Hersteller" sich dann auch ändert, wenn ich einen neuen Hersteller aus der Combobox des PG auswähle.

  • #2
    Deine GetStandardValues Methode gehört ja vermulich zu einem TypeConverter.
    Hast du den einen vollständigen TypeConverter geschrieben und deine 'Hersteller'-Property entsprechend attributiert? Wenn du etwas anderes darstellen willst als du nachher in der Property schreibst wirst du aber vermutlich einen eigenen UITypeEditor schreiben müssen.

    Comment


    • #3
      Hier der vollständige Code, den ich im Moment am "bearbeiten" bin

      Code:
      Imports System.ComponentModel
      
      Public Class VendorsConverter
          ' Da die VendorGUID vom Typ "String" ist, reicht es, dass man vom "StringConverter"
          ' ableitet
          Inherits TypeConverter
      
          ''' <summary>
          ''' Überschrieben dieser Methode
          ''' </summary>
          ''' <param name="context"></param>
          ''' <returns></returns>
          ''' <remarks></remarks>
          Public Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
              ' Mit dem Wert "True" wird angegeben, das diesses Objekt eine Reihe von Standardwerten
              ' unterstützt, die aus einer Liste ausgewählt werden können.
              Return True
          End Function
      
          ''' <summary>
          ''' Diese Methode füllt eine StandardValuesCollection mit den Werten, die man anzeigen möchte
          ''' </summary>
          ''' <param name="context"></param>
          ''' <returns></returns>
          ''' <remarks></remarks>
          Public Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
              Dim _Values As New Collections.SortedList
              Dim _dtVendors As New dsVendors.VendorsDataTable
              Dim _adVendors As dsVendorsTableAdapters.VendorsTableAdapter
              Dim _rowVendors As dsVendors.VendorsRow
      
      
              _adVendors = New dsVendorsTableAdapters.VendorsTableAdapter
              With _adVendors
                  .Connection.ConnectionString = Application.DB_CONNECTION
                  .Fill(_dtVendors)
              End With
      
              If _dtVendors.Rows.Count > 0 Then
                  For Each _rowVendors In _dtVendors.Rows
                      _Values.Add(_rowVendors.VendorsGUID, _rowVendors.VendorsName)
                  Next
              End If
      
              Return _Values
      
          End Function
      
          ''' <summary>
          ''' Optionales überschrieben dieser Methode
          ''' </summary>
          ''' <param name="context"></param>
          ''' <returns></returns>
          ''' <remarks></remarks>
          Public Overrides Function GetStandardValuesExclusive(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
      
              ' Wenn der benutzer eigene Werte eintragen kann zu den zur Verfügungstehenden, dann ist
              ' der Wert "False" zurückzugeben. Werden nur die Werte in der Liste akzeptiert, dann
              ' muss man "True" zurückgeben
              Return True
      
          End Function
      End Class

      Comment


      • #4
        Ok. Soweit ein vollständiger TypeConverter.

        Anstatt

        Code:
        Return _Values
        wolltest du ja eine StandardValuesCollection zurückgeben. Das sollte z.B so gehen

        Code:
        Return New StandardValuesCollection(_Values)
        oder wenn du nur die Values willst

        Code:
        Return New StandardValuesCollection(_Values.Values)

        Comment


        • #5
          Super - Danke

          Jetzt hab ich schon mal eine combobox zum Auswählen. Leider steht da nur zwei mal was von "System.Collections.DictionaryEntry" drin.

          Hab ich das was vergessen?

          Hab als Rückgabe das von dir vorgeschlagene

          Code:
                  Return New StandardValuesCollection(_Values)
          genommen

          Comment


          • #6
            Was willst du den sehen? Wenn es die Values sind mußt du schon _Values.Values zurückgeben.

            Comment


            • #7
              Gespeichert werden soll die GUID und sehen/auswählen soll der Benutzer den Namen

              Wenn das überhaupt geht

              Comment


              • #8
                Dann wirst du wie bereits erwähnt wohl noch einen UITypeEditor schreiben müßen.

                Edit:

                Habe das gerade mal ausprobiert mit einer Listbox als DropDown Editor. Sollte genauso (oder besser noch ein weniger geschickter) in VB umsetztbar sein.

                [Highlight=C#]
                public class MyTypeEditor : UITypeEditor
                {
                public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptor Context context)
                {
                return UITypeEditorEditStyle.DropDown;
                }

                private IWindowsFormsEditorService windowsFormsEditorService;

                public override object EditValue(System.ComponentModel.ITypeDescriptorCon text context, System.IServiceProvider provider, object value)
                {
                // DummyData
                Dictionary<string, int> data = new Dictionary<string, int>();
                data.Add("A", 1);
                data.Add("B", 2);
                data.Add("C", 3);

                windowsFormsEditorService = (IWindowsFormsEditorService)provider.GetService(ty peof(IWindowsFormsEditorService));
                if (windowsFormsEditorService != null)
                {
                ListBox dropdown = new ListBox();
                dropdown.DataSource = data.Keys.ToArray();
                dropdown.MouseDoubleClick += dropdown_MouseDoubleClick;

                windowsFormsEditorService.DropDownControl(dropdown );

                if ((dropdown.SelectedItem as string) != null)
                return data[dropdown.SelectedItem as string];
                }
                return value;
                }

                void dropdown_MouseDoubleClick(object sender, MouseEventArgs e)
                {
                if (windowsFormsEditorService != null)
                windowsFormsEditorService.CloseDropDown();
                }
                }
                [/Highlight]
                Zuletzt editiert von Ralf Jansen; 26.05.2010, 20:00.

                Comment


                • #9
                  Habe dazu eine neue Klasse erstellt - dann einen Verweis auf System.Drawing.Design hergestellt und wollte jetzt mit

                  Code:
                  Imports System.Drawing.Design.UITypeEditor
                  die entsprechende Ableitung machen. Leider gibt´s die aber da nicht. Alle anderen sind aufgelistet, nur dieser nicht. Was ist da falsch?

                  Comment


                  • #10
                    Welche Assembly hast du referenziert? UITypeEditor steckt in der System.Drawing.dll nicht, wie man annehmen könnte, in der System.Drawing.Design.dll Assembly.

                    Comment


                    • #11
                      Ja, genau diese hab ich auch referenziert.

                      Komisch

                      OK - habs gefunden. Man muss AUCH auf "System.Drawing" eine Referenz erstellen. Erst dann wird er UITypeEditor verwendbar
                      Zuletzt editiert von MyKey0815; 26.05.2010, 21:24.

                      Comment


                      • #12
                        Habe nun einen UITypeEditor erstellt. Dieser sieht wie folgt aus:

                        Code:
                        ' Diese Klasse wird benötigt, da die Angezeigten Werte, nicht den Werten entspricht, die gespeichert werden sollen
                        Public Class VendorsUITypeEditor
                        
                            Inherits System.Drawing.Design.UITypeEditor
                        
                            Public Overrides Function GetEditStyle(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.Drawing.Design.UITypeEditorEditStyle
                                Return UITypeEditorEditStyle.DropDown
                            End Function
                        
                            Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
                                Return MyBase.EditValue(context, provider, value)
                            End Function
                        
                        
                        End Class
                        Irgendwie sehe ich da keine Möglichkeit, dass ich meine Dropdown-Box füllen kann. Die ist nämlich jetzt leer. Ich brauch aber die Möglichkeit um den einen Wert letztendlich zu speichern und einen anderen in der Liste angezeigt zu bekommen.

                        Muss diese Funktionalität in "EditValue" (Also die Combobox füllen - auswählen lassen - GUID schreiben)?

                        Comment


                        • #13
                          Muss diese Funktionalität in "EditValue" (Also die Combobox füllen - auswählen lassen - GUID schreiben)?
                          Ja. Sieh dir die Implementierung in meinem C# Beispielcode an oder das Beispiel aus der MSDN Hilfe zum UITypeEditor.

                          Comment


                          • #14
                            Originally posted by Ralf Jansen View Post
                            Ja. Sieh dir die Implementierung in meinem C# Beispielcode an ....
                            Sorry, hab das grad ersst gesehen, dass du da noch was geändert hast.

                            Hab das so ähnlich jetz auch hinbekommen. Nur statt deiner statischen Daten hab ich natürlich meine Datenanbindung erzeugt

                            In der Auswahlliste ist der Name zu sehen und gespeichert wird die GUID. Soweit so richtig

                            Hab jetzt aber leider das Problem, dass im PropertyGrid die GUID erscheint. Welche Methode muss ich da überschreiben?

                            Comment


                            • #15
                              Zeig mal deine aktuelle EditValue Implementierung.

                              Den TypeConverter hast du nicht auch noch an der Property hängen oder? Du brauchst im Moment nur den UITypeEditor.


                              Edit:
                              Habe gerade erst dein Problem verstanden
                              Jetzt braucht du doch den TypeConverter. Dort mußt du die ConvertTo Methode überschreiben.
                              z.B.

                              [Highlight=C#] public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
                              {
                              if (destinationType == typeof(string))
                              return "irgendwas"; // hier Guid wieder in Namen umwandeln und zurückliefern.

                              return base.ConvertTo(context, culture, value, destinationType);
                              }
                              [/Highlight]
                              Zuletzt editiert von Ralf Jansen; 27.05.2010, 12:02.

                              Comment

                              Working...
                              X