| |
VB.NET - FortgeschritteneSteuerelement zur Laufzeit generieren | | | Autor: JuergenW | Datum: 27.05.15 15:29 |
| Hallo zusammen
ich versuche mich an einem Programm, das mit unserer CAD-Software zusammenarbeitet.
Es geht um die Erzeugung von CAD-Modell-Parameter. Dabei möchte ich dem User eine Maske zeigen, auf der er die zu erzeugenden Parameter sieht. Diese Maske ist dann von Bauteil zu Bauteil unterschiedlich.
Ich habe diese Aufgabe schon mal in HTMl/Javascript programmiert. Die Information, welche Parameter ein Bauteil braucht habe ich mit geschachtelten Arrays gemacht. siehe unten
die Informationen,wieviele Steuerelement ich brauche und ob es sich um ein Textfeld oder um eine Auswahlbox handelt war wie folgt organisiert.
hier beginnt der Teil für den 1.Parameter
ParamList[0] = new Array();
ParamList[0][0] = ("Shaft Diameter [mm]"); // Klartext des Parameters
ParamList[0][1] = ("SHAFT_DIAMETER"); // Name des Parameters
ParamList[jj][2] =("PARAM_DOUBLE"); // Type des Parameters
ParamList[0][3] = ("TEXT"); // der User hat ein Text-Feld um Eingaben zu machen
hier beginnt der Teil für den 2.Parameter
ParamList[1] = new Array();
ParamList[1][0] = ("Shaft Length [mm]");
ParamList[1][1] = ("SHAFT_LENGTH");
ParamList[1][2] = ("PARAM_DOUBLE");
ParamList[1][3] = ("TEXT");
hier beginnt der Teil für den 3.Parameter
ParamList[2] = new Array();
ParamList[2][0] = ("Type Lubrication Area");
ParamList[2][1] = ("TYPE_LUBRICATION_AREA");
ParamList[2][2] = ("PARAM_STRING");
ParamList[2][3] = ("SELECT"); // hier steht SELECT, das bedeutet der User hat eine Auswahlbox für bestimmte Eingaben
ParamList[2][4] = new Array("Spiral groove", "Flat Area", "None", "Other", "tbd") // das wären die Werte, die in der Auswahlbox wählbar sein sollen
hier beginnt der Teil für den 4.Parameter; ist genauso wie beim 3.Parameter
ParamList[3] = new Array();
ParamList[3][0] = ("Type");
ParamList[3][1] = ("TYPE");
ParamList[3][2] = ("PARAM_STRING");
ParamList[3][3] = ("SELECT");
ParamList[3][4] = new Array("Cross Shaft", "Bar Shaft long", "Bar Shaft short", "Other", "tbd")
ParamList[4] = new Array();
ParamList[4][0] = ("Material");
ParamList[4][1] = ("MATERIAL");
ParamList[4][2] = ("PARAM_STRING");
ParamList[4][3] = ("TEXT");
ParamList[5] = new Array();
ParamList[5][0] = ("Weight [kg]");
ParamList[5][1] = ("WEIGHT");
ParamList[5][2] = ("PARAM_DOUBLE");
ParamList[5][3] = ("TEXT");
ParamList[6] = new Array();
ParamList[6][0] = ("Related GKN Part No");
ParamList[6][1] = ("WT_PART_NO");
ParamList[6][2] = ("PARAM_STRING");
ParamList[6][3] = ("TEXT");
ParamList[7] = new Array();
ParamList[7][0] = ("GKN Classification");
ParamList[7][1] = ("GKN_CLASSIFICATION");
ParamList[7][2] = ("PARAM_STRING");
ParamList[7][3] = ("TEXT");
break;
Kann ich soetwas (verschachtelte Arrays oder anders) auch mit VB machen. Dabei ist zu beachten, dass die Typen der Elemente meistens Stings sind, es kann aber auch vorkommen, dass es ein Array ist. Das ist der Fall wenn statt TEXT --> SELECT steht. Man sieht dann das das nächste Element im Array wieder ein Array ist.
Das größte Problem wird sein mich verständlich ausgedrückt zu haben.
Wie ich die Infos aus der Struktur dann auslese und Steuerelemente draus mache ist wieder ein andere Sache, aber das versuche ich dann selbst.
Ich bin zur Zeit noch ziemlich hilflos und bin für jede Anregung dankbar.
Viel Grüße
Jürgen | |
Re: Jagged Array | | | Autor: JuergenW | Datum: 27.05.15 21:43 |
| Es geht schlussendlich schon um Controls. Wie viele ich für eine Maske brauche und ob es einmal eine TextBox ist oder eine Auswahlliste, das möchte ich dem/n Array/s speichern.
Aus diesen Angaben würde ich folgendes generieren:
Label mit .Text = [u]Shaft Diameter [mm] daneben eine TextBox, die den Wert für Shaft Diameter aufnimmt. PARAM_DOUBLE ist für das CAD-Programm wichtig, in dem Fall würde ein Parameter erzeugt, der einen DOUBLE-Wert aufnimmt.
hier beginnt der Teil für den 1.Parameter
ParamList[0] = new Array();
ParamList[0][0] = ("Shaft Diameter [mm]"); // Klartext des Parameters
ParamList[0][1] = ("SHAFT_DIAMETER"); // Name des Parameters
ParamList[jj][2] =("PARAM_DOUBLE"); // Type des Parameters
ParamList[0][3] = ("TEXT"); // der User hat ein Text-Feld um Eingaben zu machen
das hier würde ergeben:
Label mit .Text = [u]Type und daneben eine Auswahlbox, in der ich aus Cross Shaft, Bar Shaft Long usw
einen Wert auswählen kann.
hier beginnt der Teil für den 4.Parameter; ist genauso wie beim 3.Parameter
ParamList[3] = new Array();
ParamList[3][0] = ("Type");
ParamList[3][1] = ("TYPE");
ParamList[3][2] = ("PARAM_STRING");
ParamList[3][3] = ("SELECT");
ParamList[3][4] = new Array("Cross Shaft", "Bar Shaft long", "Bar Shaft short", "Other", "tbd")
Das Erzeugen der Controls kommt als 2.Schritt an die Reihe.
Der erste Schritt ist, und um den geht es mir, wie kann ich in VB.NET diese Infos abspeichern.
In der HTML-Welt habe ich das mit einem Array geschafft.
Beim Type-Parameter sieht man, dass von [3][0] bis [3][3] jeweils ein String gespeichert wurde.
In [3][4]aber ein Array , dessen Inhalt in einer Zeile initialisiert wurde.
Für mich stellt sich nur die Frage wie mache ich das am geschicktesten. Mit Array, Listen oder was VB.NET mit Bordmitteln zur Verfügung stellt. Draus die Controls zu erstellen mache ich mir erst später Gedanken.
Ich schau mir jetzt mal an was unter dem Link zu finden ist.
Viele Grüße
Jürgen | |
Klasse 'ParameterInfo' | | | Autor: Manfred X | Datum: 28.05.15 06:21 |
| Da ich Herkunft und Verwendung Deiner CAD-Daten nicht kenne,
habe ich eine simple Klasse ohne Datenbindung erstellt, die ParameterInfos
aufnehmen und ggf. auch passende Controls auf einem
gegebenen Container (z.B. Win.Form) erstellen kann.
Instanzen dieser Klasse können in einer generischen Liste verwaltet werden.
Die Organisation des Event-Handling der dynamisch erstellten Controls
wäre zu diskutieren!
Public Class ParameterInfo
Public Enum ParamType
[Double]
Text
TextArray
DoubleArray
End Enum
Public Enum ControlType
TextBox
Combobox
ListBox
Button
End Enum
Dim _param_name As String
Public ReadOnly Property Param_Name As String
Get
Return _param_name
End Get
End Property
Dim _param_type As ParamType
Public ReadOnly Property Param_type As ParamType
Get
Return _param_type
End Get
End Property
Public Property Param_Value As Object 'einer der Parametertypen
Dim _control_type As ControlType
Dim _control_location As Point
Dim _control_size As Size
'Position und Größe des zugeordneten Labels
'Diese Angaben könnten auch relativ zu den entsprechenden
'Control-Eigenschaften berechnet werden.
Dim _label_location As Point
Dim _label_size As Size
''' <param name="Param_Name">eindeutiger Name des Parameters
''' (=Text im Label, Name des Control)</param>
''' <param name="Param_Type">Datentyp des Parameters</param>
''' <param name="Param_Value">Wert des Parameters
''' (wird im Control angezeigt)</param>
''' <param name="Control_Type">Typ des Control</param>
''' <param name="Control_Location">Position des Control auf dem Container
''' (gegeben in CreateControl)</param>
''' <param name="Control_Size">Größe des Control (Pixel)</param>
''' <param name="Label_Location">Position des Label,
''' das dem Control zugeordnet ist</param>
Public Sub New _
(Param_Name As String, Param_Type As ParamType, _
Param_Value As Object, _
Control_Type As ControlType, _
Control_Location As Point, Control_Size As Size, _
Label_Location As Point, Label_Size As Size)
_param_name = Param_Name
_param_type = Param_Type
_Param_Value = Param_Value
_control_type = Control_Type
_control_location = Control_Location
_control_size = Control_Size
_label_location = Label_Location
_label_size = Label_Size
End Sub
Public Function CreateControl(ByVal f As Control) As Control
'f ist der Container, in dem die Controls erstellt werden
Dim ctl As Control = Nothing
'Label zum Control erstellen und positionieren
Dim lbl As New Label With _
{.Parent = f, _
.Location = _label_location, .Size = _label_size, _
.Text = _param_name, .AutoSize = False}
'Control erstellen und aktuellen Value eintragen
Select Case _control_type
Case ControlType.Button
ctl = New Button With _
{.Text = GetValue(0).ToString}
Case ControlType.TextBox
ctl = New TextBox With _
{.Text = GetValue(0).ToString}
Case ControlType.Combobox
Dim cbo As New ComboBox
cbo.Items.AddRange(GetValue())
ctl = cbo
Case ControlType.ListBox
Dim lbo As New ListBox
lbo.Items.AddRange(GetValue)
ctl = lbo
End Select
If ctl IsNot Nothing Then
'allgemeine Control-Eigenschaften
With ctl
.Parent = f
.Name = _param_name
.Location = _control_location
.Size = _control_size
End With
End If
Return ctl
End Function
Private Function GetValue() As Object()
'Cast der Parameter-Value-Typen
Dim items() As Object = Nothing
If TypeOf _Param_Value Is Double() Then
Dim dbl As Double() = CType(_Param_Value, Double())
ReDim items(dbl.Length - 1)
For i As Integer = 0 To dbl.Length - 1
items(i) = dbl(i)
Next i
ElseIf TypeOf _Param_Value Is String() Then
Dim str As String() = CType(_Param_Value, String())
ReDim items(str.Length - 1)
For i As Integer = 0 To str.Length - 1
items(i) = str(i)
Next i
Else
ReDim items(0)
items(0) = _Param_Value
End If
Return items
End Function
End Class | |
Anwendungsbeispiel | | | Autor: Manfred X | Datum: 28.05.15 06:23 |
| Public Class frmDynCtl
'Liste der Parameter
Dim pil As New List(Of ParameterInfo)
Private Sub frmDynCtl_Load(sender As System.Object, _
e As System.EventArgs) Handles MyBase.Load
Dim control_height As Integer = 50
Dim control_size As New Size(150, 30)
Dim label_size As New Size(80, 30)
'Parameter_Infos erstellen und auflisten
pil.Add(New ParameterInfo _
("TBO1_Name", ParameterInfo.ParamType.Text, _
"TBO1_Value", _
ParameterInfo.ControlType.TextBox, _
New Point(100, 20), control_size, _
New Point(10, 20), label_size))
pil.Add(New ParameterInfo _
("TBO2_Name", ParameterInfo.ParamType.Double, 5247.15, _
ParameterInfo.ControlType.TextBox, _
New Point(100, 20 + control_height), control_size, _
New Point(10, 20 + control_height), label_size))
pil.Add(New ParameterInfo _
("LBO1_Name", ParameterInfo.ParamType.TextArray, _
New String() {"LBO1_Item1", "LBO1_Item2", "LBO1_Item3"}, _
ParameterInfo.ControlType.ListBox, _
New Point(100, 20 + control_height * 2), control_size, _
New Point(10, 20 + control_height * 2), label_size))
pil.Add(New ParameterInfo _
("CBO1_Name", ParameterInfo.ParamType.DoubleArray, _
New Double() {10.7, 12.65, 3.561}, _
ParameterInfo.ControlType.Combobox, _
New Point(100, 20 + control_height * 3), control_size, _
New Point(10, 20 + control_height * 3), label_size))
pil.Add(New ParameterInfo _
("BTN1_Name", ParameterInfo.ParamType.Text, "BTN1_Value", _
ParameterInfo.ControlType.Button, _
New Point(100, 20 + control_height * 4), control_size, _
New Point(10, 20 + control_height * 4), label_size))
'Das ContainerControl
Dim pan As New Panel With _
{.Parent = Me, .Top = 10, _
.Width = 300, .Height = control_height * 5, _
.BackColor = Color.LightGray}
'benötigte Controls für die ParameterInfos erstellen
'und mit den Eventhandler-Routinen kombinieren
For Each pi As ParameterInfo In pil
Dim ctl As Control = pi.CreateControl(pan)
If TypeOf ctl Is ComboBox Then
Dim cbo As ComboBox = DirectCast(ctl, ComboBox)
AddHandler cbo.SelectedIndexChanged, _
AddressOf Selectedindex_changed
ElseIf TypeOf ctl Is TextBox Then
Dim tbo As TextBox = DirectCast(ctl, TextBox)
AddHandler tbo.TextChanged, AddressOf text_changed
Else
AddHandler ctl.Click, AddressOf Ctl_click
End If
Next pi
End Sub
Public Sub Ctl_click(ByVal sender As Object, e As EventArgs)
Dim ctl As Control = DirectCast(sender, Control)
MsgBox(ctl.Name & " wurde gedrückt")
End Sub
Public Sub Selectedindex_changed(ByVal sender As Object, e As EventArgs)
Dim cbo As ComboBox = DirectCast(sender, ComboBox)
MsgBox("Index " & cbo.SelectedIndex.ToString & " wurde ausgewählt")
End Sub
Public Sub text_changed(ByVal sender As Object, e As EventArgs)
Dim tbo As TextBox = DirectCast(sender, TextBox)
MsgBox("Neuer Text: " & tbo.Text)
End Sub
End Class
Beitrag wurde zuletzt am 28.05.15 um 06:25:43 editiert. | |
Re: Anwendungsbeispiel | | | Autor: JuergenW | Datum: 28.05.15 10:25 |
| Hallo Manfred
vielen Dank, dass du soviel Mühe machst. Ich werde deine Vorschlag sobald als möglich einbauen und mich dann wieder melden.
Ich wollte mich aber vor schon bei dir bedanken.
Viele Grüße
Jürgen | |
Re: Anwendungsbeispiel | | | Autor: JuergenW | Datum: 01.06.15 12:55 |
| Hallo Manfred
das sieht doch schon sehr gut aus.
Wenn ich den Code analysiere, so hänge ich immer wieder hier fest. Ich kann nicht ergründen wozu das gebraucht wird.
Public Enum ParamType
[Double]
Text
TextArray
DoubleArray
End Enum
Public Enum ControlType
TextBox
Combobox
ListBox
Button
End Enum Das Zweite ist immer noch das Thema der Archivierung der zusammengeörigen Parameter.
Ich hol noch mal ein bisschen aus.
In unserer Konstruktionsabteilung gibt es zB Schrauben: Wenn ich eine Schraube im CAD-System geladen habe wähle ich aus einem TreeView den Eintag <<SCHRAUBE>> aus, dann weiss das Programm, welche Parameter ich am Bauteil benötige, wie etwa Länge, Gewinde, Festigkeitsgrad, Kopfhöhe.
/*
alle für eine Klassifikation notwendigen Model-Parameter gültig für "PRT" und "ASM"
*/
function addClassModelParameter(PartName) //PartName = SCHRAUBE
switch (PartName)
{
/* ================================= */
case "SERVICE_KIT":
/* ================================= */
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Project No");
ParamList[jj][1] = ("PROJECT_NO");
ParamList[jj][2] = ("PARAM_STRING");
ParamList[jj][3] = ("TEXT");
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Part Description");
ParamList[jj][1] = ("PART_DESCRIPTION");
ParamList[jj][2] = ("PARAM_STRING");
ParamList[jj][3] = ("TEXT");
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Weight [kg]");
ParamList[jj][1] = ("WEIGHT");
ParamList[jj][2] = ("PARAM_DOUBLE");
ParamList[jj][3] = ("TEXT");
.
.
.
/* ================================= */
case "SCHRAUBE":
/* ================================= */
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Designation");
ParamList[jj][1] = ("DESIGNATION");
ParamList[jj][2] = ("PARAM_STRING");
ParamList[jj][3] = ("TEXT");
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Thread Diameter [mm]");
ParamList[jj][1] = ("THREAD_DIAMETER");
ParamList[jj][2] = ("PARAM_DOUBLE");
ParamList[jj][3] = ("TEXT");
.
.
.
/* ================================= */
case "SPECIAL_NUT":
/* ================================= */
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Designation");
ParamList[jj][1] = ("DESIGNATION");
ParamList[jj][2] = ("PARAM_STRING");
ParamList[jj][3] = ("TEXT");
ParamList[++ jj] = new Array();
ParamList[jj][0] = ("Thread Diameter [mm]");
ParamList[jj][1] = ("THREAD_DIAMETER");
ParamList[jj][2] = ("PARAM_DOUBLE");
ParamList[jj][3] = ("TEXT");
.
.
.
}
Da wir ca 300 verschiedene Bauteilklassen haben und jedes Bauteil mindesten 5 Parameter hat ist diese [u]Liste/Aufzählung/verschachteltes Array natürlich sehr lang gewesen.
In deinem Beispiel wird zu Anschauungszwecken direkt eine "Parameter-Maske" zusammen gebaut.
Kann man sich in Vb.net vorstellen diese [u]lange Liste zu hinterlegen. Dann übergibt das Hauptprogramm den Bauteilnamen an [u]function addClassModelParameter(PartName) und über PartName wird der entsprechende Bereich gefunden und die darin enthaltenen Parameter erzeugt.
Das Konstrukt dieser Liste in VB.net ist also der Knackpunkt.
Ich bin schon ganz happy mit deinem Programm und passe es meinem Code noch ein bisschen an.
Vielen, vielen Dank
Jürgen
| |
Re: Anwendungsbeispiel | | | Autor: Manfred X | Datum: 01.06.15 13:29 |
| Hallo!
[I]In unserer Konstruktionsabteilung gibt es zB Schrauben:
Wenn ich eine Schraube im CAD-System geladen habe wähle ich aus einem TreeView
den Eintag <<SCHRAUBE>> aus, dann weiss das Programm, welche Parameter ich
am Bauteil benötige, wie etwa Länge, Gewinde, Festigkeitsgrad, Kopfhöhe. [/I]
Schön, wenn das Programm das alles weiß.
Aber woher bezieht es diese Kenntnisse?
Vermutlich gibt es eine Datenbank, in der die erforderlichen Angaben zu den Bauteilen
verzeichnet sind und die bei Wahl eines Bauteils aus den DB-Tabellen abgefragt werden.
Deine Datentrukturen erhälst Du in dem Fall aus einer Datenbankabfrage z.B. in einer
Datatable.
Was ebenfalls unklar ist: Wie sieht es mit den Ereignis-Handlern der Controls in den
dynamisch erzeugten Dialog-Formularen aus? Sind bei allen Bauteilen stets für einen bestimmten
Control-Typ jeweils die gleichen Ereignisse mit dem gleichen Code zu verarbeiten?
Oder sind die Formulare spezifisch aufzubauen?
Was ist eigentlich die Funktion dieser Dialoge?
Eventuell müssen in der Bauteile-Datenbank zusätzliche Angaben hinterlegt werden,
aus denen hervorgeht, wie das entsprechende Formular zu gestalten ist (Enumeration verschiedener
Dialogtypen).
Enumerationen (=Liste benannter numerischer Werte) sorgen dafür, daß eine Auswahl eindeutig
wird (z.B. zeigt Intellisense die möglichen Alternativen, die auch mit einem Kommentar versehen
sein können).
| |
Re: Anwendungsbeispiel | | | Autor: JuergenW | Datum: 01.06.15 13:56 |
| Hallo
"das Programm weiss" ist jetzt suboptimal ausgedrückt.
Die Umsetzung in HTML/Javscript hatte keine Datenbank oder sonstige Hilfsmittel also auch kein PHP und kein MYSql nichts dergleichen.
Es gab eine Auswahlfeld (wäre dann das TreeView) mit dem er die für sein Bauteil passende "Klassifikation" ausgewählt hat. der ausgewählte Wert wurde der Variable ParamName übergeben. Dann hatte die Variable ParamName den Wert "SCHRAUBE" Mit dieser Variable wurde die (ich nenne sie wieder) lange Liste durchsucht, bis auf den Wert SCHRAUBE gestoßen ist. In dem Abschnitt SCHRAUBE waren dann die erforderlichen Parameter gefunden. Das HTML-Script hat aus diesen Angaben eine Tabelle generiert, in die der User dann die passenden Werte reingeschieben hat. Nachdem alles ausgefüllt war wurde ein OK Button gedrücktn und die CAD-Modell-Parameter erzeugt. Es gab nur Text/Integer und Double Werte der Inhalt dazu kommt vom User.
Die Tabelle für eine Schraube sah natürlich anders aus als für ein Getriebegehäuse. Direkt nach dem Auswählen in dem Auswahlfeld wurde diese Tabelle zusammengebaut.
Ich habe ja schon ein paar mal Ausschnitte aus dieser langen Liste mitgeschickt. Was in javascript möglich war, versuche ich nun in VB abzubilden.
Schade, dass man hier keine Bilder hochladen kann, dann wäre es wohl einfach zu erklären.
Viele Grüsse | |
Re: Anwendungsbeispiel | | | Autor: Manfred X | Datum: 01.06.15 14:57 |
| Offensichtlich ist das erste, was Du tun mußt:
Eine SQL-Datenbank erstellen - eventuell Multiuserfähig im Firmen-Netzwerk -
und diese lange Liste dort in eine DB-Tabelle oder in miteinander verknüpfte
(normalisierte) Tabellen eintragen.
Ob noch weitere Angaben abzulegen sind - z.B. zur Gestaltung des Formulars -
kann ich nicht beurteilen.
Dafür gibt es im Visual Studio geeignete Assistenten.
Das Programm fragt die jeweils benötigten Bauteil-Daten aus der Datenbank ab
(ADO.Net-Klassen) und verarbeitet die erhaltenen Informationen.
| |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevISDN 1.0
Überwachung aller eingehender Anrufe!
Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Weitere InfosTipp des Monats Neu! sevEingabe 3.0
Einfach stark!
Ein einziges Eingabe-Control für alle benötigten Eingabetypen und -formate, inkl. Kalender-, Taschenrechner und Floskelfunktion, mehrspaltige ComboBox mit DB-Anbindung, ImageComboBox u.v.m. Weitere Infos
|