Community,
I am developing an app (iLogic rule and a dynamic .NET form) to edit sheet metal styles in a multibody part.
I am using DatGridView tables. I have built the table with standard columns, but have been unsuccessful to add or insert a DataGridViewComboBoxColumn.
A DataGridViewComboBox column would allow the user to select from a drop-down box a different sheet metal style for each solid body in the part.
The code shown below:
Function BuildBaseTable() As DataTable
Dim myComboBoxColumn As DataGridViewComboBoxColumn = New DataGridViewComboBoxColumn
myComboBoxColumn.HeaderText = "SMStyleC"
myComboBoxColumn.Name = "MyCombo"
myComboBoxColumn.Items.Add("Style 1")
myComboBoxColumn.Items.Add("Style 2")
myComboBoxColumn.Items.Add("Style 3")
myComboBoxColumn.Items.Add("Style 4")
' Add columns
myTable.Columns.Add("Body Name", GetType(String))
myTable.columns.insert(1, myComboBoxColumn) 'ERROR OCCURS ON THIS LINE
myTable.Columns.Add("SM Style", GetType(String))
myTable.Columns.Add("Inv Material", GetType(String))
myTable.Columns.Add("Thickness", GetType(String))
' Set table name
myTable.TableName = "TableName"
' Return the updated table
Return myTable
End Function
results in this error:
Rule Compile Errors in SM_MB_Edit, in Sheet_Metal_MultiBody_Editing_01.ipt
Error on Line 79 : 'insert' is not a member of 'System.Data.DataColumnCollection'.
Please ignore the line number mismatch (12 and 79) since this is only a portion of the code.
I have searched many DataGridViewComboBoxColumn examples on the internet, but I have not been able to adapt the code for this application.
I have successfully used VB.NET examples in Visual Studio to build DGV tables with DGV comboboxes, but not in an iLogic rule.
Could anyone direct me to a resource that explains how to add a DataGridViewComboBoxColumn to this DataGridView table for use in Inventor? I hope to avoid a DLL or addin solution.
I have attached the entire SheetMetal-Multibody-Edit (SM_MB_Edit) rule for your convenience.
I am using Inventor 2022.
Thank you for your time and attention. I look forward to your replies.
Regards,
Jerry
Solved! Go to Solution.
Solved by Michael.Navara. Go to Solution.
Here is sample how to use DataGridView with combo column for sheetmetal style selection
It is a copy of local rule. It can be converted to external rule
AddReference "System.Drawing.dll"
Imports System.Collections.Generic
Imports System.Windows.Forms
Sub Main()
MainInternal()
End Sub
''' <summary>
''' Usage sample
''' </summary>
Sub MainInternal()
Dim f As New IC_11598451Dlg(ThisDoc.Document)
If f.ShowDialog() <> DialogResult.OK Then Return
Dim result = f.GetResult()
For Each rowInfo As IC_11598451Dlg.RowInfo In result
Logger.Debug("Body: {0}, Style: {1}", rowInfo.BodyName, rowInfo.StyleName)
Next
End Sub
''' <summary>
''' Dialog with dataGridView and column sample
''' </summary>
Public Class IC_11598451Dlg
Inherits Form
#Region "My Implementation"
Public Sub New()
InitializeComponent()
SetDataGridView(Nothing)
End Sub
Public Sub New(part As PartDocument)
InitializeComponent()
SetDataGridView(part)
End Sub
Sub SetDataGridView(part As PartDocument)
If part Is Nothing Then Return
Dim smDef As SheetMetalComponentDefinition = part.ComponentDefinition
'Body name cell
Dim bodyNameCell = New DataGridViewTextBoxCell
'Sheetmetal style cell
Dim styleNameCell = New DataGridViewComboBoxCell()
For Each smStyle As SheetMetalStyle In smDef.SheetMetalStyles
styleNameCell.Items.Add(smStyle.Name)
Next
'Create columns
DataGridView1.Columns.Add(New DataGridViewColumn(bodyNameCell))
DataGridView1.Columns.Add(New DataGridViewColumn(styleNameCell))
'Add data
For Each surfaceBody As SurfaceBody In smDef.SurfaceBodies
Dim bodyName As String = SurfaceBody.Name
Dim styleName As String = smDef.GetBodySheetMetalStyle(SurfaceBody).Name
DataGridView1.Rows.Add(bodyName, styleName)
Next
End Sub
Public Function GetResult() As List(Of RowInfo)
Dim result = New List(Of RowInfo)
For Each row As DataGridViewRow In DataGridView1.Rows
result.Add(New RowInfo(Row.Cells(0).Value, Row.Cells(1).Value))
Next
Return result
End Function
Class RowInfo
Public BodyName As String
Public StyleName As String
Sub New(bodyName As String, styleName As String)
Me.BodyName = bodyName
Me.StyleName = styleName
End Sub
End Class
#End Region
Friend WithEvents Button1 As Button
Friend WithEvents DataGridView1 As DataGridView
Private Sub InitializeComponent()
Me.DataGridView1 = New System.Windows.Forms.DataGridView()
Me.Button1 = New System.Windows.Forms.Button()
CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
'DataGridView1
'
Me.DataGridView1.AllowUserToAddRows = False
Me.DataGridView1.AllowUserToDeleteRows = False
Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.DataGridView1.Location = New System.Drawing.Point(0, 0)
Me.DataGridView1.Name = "DataGridView1"
Me.DataGridView1.Size = New System.Drawing.Size(240, 150)
Me.DataGridView1.TabIndex = 0
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(174, 196)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(75, 23)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Button1"
Me.Button1.UseVisualStyleBackColor = True
'
'IC_11598451Dlg
'
Me.ClientSize = New System.Drawing.Size(284, 261)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.DataGridView1)
Me.Name = "IC_11598451Dlg"
CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
DialogResult = DialogResult.OK
Close()
End Sub
End Class
Thank you for the great solution on adding a combobox to the DGV!
It is interesting that your solution uses a ComboBoxCell instead of a ComboBoxColumn.
Could you explain why my ComboBoxColumn method failed?
Next step will be to make the solid bodies update when a new style is selected.
If I have trouble, I will post again for assistance.
Thanks again, Michael. Great work!
Regards,
Jerry
I have been working through your code today.
What is the benefit of using "IC_11598451Dlg". I have never seen that style of programming in iLogic.
What is being converted in the CType statements?
What is the benefit or purpose of declaring the New function twice? First with nothing and second with a part.
Regards,
Jerry
Sorry I can't explain it, because I'm not too familiar with DataGridView, usually I try to avoid to use this object except show results from SQL queries etc. Rather then I implement my own UserControl and its instances I push to TableLayoutPanel.
At lines 20-23 you have sample, how to query result from DataGridView. You can replace simple logging line with more complex function where you get SurfaceBody by its name and select appropriate SheetMetalStyle by its name and set the style with one of this two methods
The IC_11598451Dlg is a class derived from System.Windows.Forms.Form.
Sorry for the strange name, but it is used by me to distinguish rules posted to this forum. It is combination of 'IC_' prefix (shortcut for Inventor Customization, older name of this forum), '11598451' is ID of this thread (part of URL address), 'Dlg' is shortcut for Dialog.
From line 92 below is automatically generated code from VisualStudio forms editor. I don't know why it uses CType.
I need to declare two different constructors (Public Sub New()...), because for design time I need parameterless constructor (VS Forms editor requirement), but for usage I want to specify the source part at the beginning and I don't want to specify the source part later.
No worries, Michael.
Thanks for the explanation of the IC_...
I see now in lines 20-23 where I can apply the new sheet metal style.
So I followed your example by building the DGV table using Visual Studio and then copy the text from the VB file into the iLogic Editor. So much better than typing all that code by hand!
I'm still learning about constructors. Thanks for the explanation.
You mentioned that you would have developed a UserControl and pushed it to a TableLayoutPanel.
If there is a better approach to editing sheet metal styles for solid bodies, I would welcome the opportunity to learn more.
Thanks again for all your help.
Regards,
Jerry
I am finally getting back to this project.
I was able to get the sheet metal multi-bodies to update with the sheet metal style selected in the DataGridView dialog interface.
The updates occur after the user selects the Done button. I would like to implement an "Apply" button so the user can change styles, apply the changes to see the effects, but keep the dialog open in case the user wants to make additional changes.
Since the Done button got the results of the dialog box after it closed, the Apply button will need to get the current status of the DataGridView. I am struggling with classes and shared objects in order to access the part (sheet metal) info while the dialog box is still open.
Can you are someone in the Community direct me to examples to help me with my code?
I have attached a sample part which includes the iLogic rule developed by Michael and enhanced by myself. See the sub named, btnApply_Click, within the code.
Thank you for your time and attention. I look forward to your replies.
Regards,
Jerry
In this case you have two possibilities. Create delegate function or create custom event. I recommend you to use the second option.
At first you need to declare custom event in dialog
#Region "Custom event"
Public Event OnApply As OnApplyHandler
Public Delegate Sub OnApplyHandler(sender As Object, args As OnApplyHandlerArgs)
Public Class OnApplyHandlerArgs
Private ReadOnly _result As List(Of RowInfo)
Public Sub New(result As List(Of RowInfo))
_result = result
End Sub
Public ReadOnly Property Result As List(Of RowInfo)
Get
Return _result
End Get
End Property
End Class
#End Region
When user clicks the Apply button, you need to fire this event
Public Sub btnApply_Click(sender As Object, e As EventArgs) Handles btnApply.Click
'Fire custom event if any
Dim args As OnApplyHandlerArgs = New OnApplyHandlerArgs(GetResult())
RaiseEvent OnApply(Me, args)
End Sub
And also you need to assign your handler to this event at main rule level
Sub MainInternal()
Dim f As New IC_11598451Dlg(ThisDoc.Document)
'Add custom event handler
AddHandler f.OnApply, AddressOf IC_11598451Dlg_OnApply
If f.ShowDialog() <> DialogResult.OK Then Return
Dim result = f.GetResult()
Call ApplyStyleChanges(result)
Return
End Sub
Private Sub IC_11598451Dlg_OnApply(sender As Object, args As IC_11598451Dlg.OnApplyHandlerArgs)
Dim result As List(Of IC_11598451Dlg.RowInfo) = args.Result
ApplyStyleChanges(result)
End Sub
Complete code is in attached part file as "Michael Navara DataGridView Table_v2"
Outstanding!!
I would like to continue to improve this utility:
These would be behaviors similar to the BOM command in an assembly.
As the rule is now, it is very useable.
Given the above mentioned goals, is this iLogic rule the best approach?
In December you mentioned a UserControl and a TableLayoutPanel. Would this be a DLL?
I am learning a lot through your examples, Michael, and I appreciate your generosity of time and knowledge.
I look forward to your feedback.
Regards,
Jerry
Very useful!
Is it possible to add the apply button in/for each row inside of the datagrid?
use cases could be:
run an external rule for one file of a certain row
send a certain part list row to manufacturing part list in the ERP while other rows shall be untouched
Can't find what you're looking for? Ask the community or share your knowledge.