Creating a checkbox column in Objectlistview with Revit - vb.net

I am trying to create a list of sheets in Revit using the ObjectListView control using vb.net API. I have managed to use the column aspectgetter and aspect putter to create delegates that get the parameter values for various parameters in the sheet family, and this seems to be working correctly. Now I want to have a check box column at the front of the list to allow the user to make a selection of sheets - there does not seem to be an easy way to do this as I believe I need to tie the checkboxes to a parameter in the sheet family?
I have experimented with creating a boolean shared parameter in the sheet family and then tying the checkbox column to this using the BooleanCheckStateGetter/Putter but it doesn't seem to be working?
.BooleanCheckStateGetter = Function(ByVal rowObject)
Return CType(CType(rowObject, ViewSheet).LookupParameter("checked").AsInteger, Boolean)
End Function
.BooleanCheckStatePutter = Function(rowObject, newvalue)
CType(rowObject, ViewSheet).LookupParameter("checked").Set(If(newvalue = True, 1, 0))
Return newvalue
End Function

Related

Access VBA - Type Mismatch when working with Combo Boxes (Multi Valued Fields)

I have a form that displays a single record at a time, and allows the record to be edited by displaying it all in Text Boxes and Combo Boxes. Some of these are ComboBoxes based off of lookup fields, where the values are pulled from a preset list (multi-valued fields).
After that, I have a class module with a property defined for each field in the record (a FirstName Property, a LastName Property, an Address Property... you get the idea). I have a function that creates an object from the class, and then takes the values from the form and assigns them to the corresponding property. This works fine for most of the fields, but as soon as it gets to the first Combo Box (multiple selection), it throws a Type Mismatch error. Code I'm using is:
If Me.Issue <> vbNullString Then
ProfileObj.Issue = Me.Issue
End If
'Me.Issue is the combobox on the form - this is in the forms module
'ProfileObj is the class instance
In case you wanted to see the Property in the class module for the ProfileObj object:
Private ProfileIssue As String
'... other variable declarations
Property Get Issue() As String
Issue = ProfileIssue
End Property
Property Let Issue(rData As String)
ProfileIssue = rData
End Property
I've also tried using Me.Issue.Value, Me.Issue.Text, and Me.Issue.Column(0) to refer to the Combo Box, but none of these have worked either. I even tried using CStr(Me.Issue), to no avail. How can I take whatever's displayed int the combo box and assign it to a String variable?
I figured it out...
I needed to read the text from each Combo Box with each box's .Text property. I had tried that inside of the If statements, but not for the actual comparison that the If statement was built on. The working version of the code now reads:
Me.Issue.SetFocus 'You have to set focus in order to read the text, dont ask me why
If Me.Issue.Text <> vbNullString Then 'This is where my code wasn't working
.Issue = Me.Issue.Text 'I had tried it here before, but the code never got there since the line before failed
End If

Passing a checkbox control to a function

I am using Access 365 and VisualBasic. I have a number of checkboxes on a form that I want to display just a subset of these at a time, so I want to reposition the top of the checkboxes so that no matter which are currently displayed, I can make them line up nicely.
So, I have declared an array of checkboxes that I want to dynamically add those checkboxes to display:
' Array holding the checkboxes that will be displayed, depending upon species, sex, etc.
Dim arrCheckBoxes(cNumCheckboxes) As CheckBox
Then as I determine that a specific check box should be shown, I want to add it to the array at the next available position using this function (which will also update the next available position):
Private Sub AddCheckbox(ByRef arrCheckBoxes() As CheckBox, ByRef chkNew As CheckBox, ByRef intCurrentCheckbox)
intCurrentCheckbox = intCurrentCheckbox + 1
arrCheckBoxes(intCurrentCheckbox) = chkNew
End Sub
My problem is that in the code that calls the AddCheckbox function, I cannot figure out how to pass the check box. I am using the following code (CatNeuter is the checkbox from my form).
Call AddCheckbox(arrCheckBoxes, Me.CatNeuter, intCurrentCheckbox)
However, Me.CatNeuter is always 0, so I think I am getting just the value, and not the checkbox control itself. I've tried numerous different methods such as:
Me.Controls!CatNeuter
Me.Controls("CatNeuter")
But I just cannot figure out how to pass the actual checkbox so I can then go through the array and change the Top property for each checkbox.
Regards,
Lise
You need to use Set for objects:
Set arrCheckBoxes(intCurrentCheckbox) = chkNew

Number Picker in Access / VBA

I am trying to put a number picker in a form in MS Access 2007. Here's an example of what I am trying to make:
I cannot find this in the default form controls, and have tried to make one myself using a listbox. Listboxes can be modified to look just like the number picker above, however the arrows only change the view, of the list, and not the actual selection (that is the value). For example, with the list box, if I have it range from 1 to 3, and default at 1 - when I change it to 2 via the arrows, the value of the listbox does not change, and is still one.
Does anyone know how to get a number picker in Access?
So you want to create a list of numbers and allow users to change the value displayed (AND stored as the control's value) using up and down arrows, such that they select the next or previous in the list.
I would suggest creating a text box and two buttons. Populate an array with the list of values. When a button is clicked it would:
A. Find the position in the array of any value already entered into the text box (eg loaded from a database)
B. Get the next or previous item from the array.
The array is populated as required (probably when the form is opened).
If you just need to allow the user to enter a whole integer number (ie a number spinner) you would do as follows:
Create one using a (locked) textbox and two buttons. Just add a textbox (name it something like txtValue) and two buttons (btnUp and btnDown), then add code like this to the Click event of those buttons:
Private Sub btnUp_Click()
Me.txtValue = Nz(Me.txtValue, 0) + 1
End Sub
Private Sub btnDown_Click()
Me.txtValue = Nz(Me.txtValue, 0) - 1
End Sub
You could add if statements to limit the data being entered
Or you can use a 3rd party control.
http://www.fmsinc.com/microsoftaccess/controls/components/spin-button/index.html
There are probably more, but be aware that using these sorts of controls in Access is unsupported, and there is no guarantee moving forward that they will work in Access. You're far better off using the native methods described earlier.

Is there a way to allow only unique values in a column of an Infragistics UltraWinGrid?

I'm using an Infragistics UltraWinGrid with a column of drop-down boxes. I don't want the user to be able to select the same value for multiple rows in that column. Is there a simple (or heck, I'd settle for advanced) way to do this?
I'm using VB.NET
-EDIT-
I tried setting a filter on the data source for the drop-down box. But when I did that, the values in the other boxes in that column started disappearing (not the values themselves, but the descriptions that they were supposed to represent, so instead of reading "Information", it just said "1"). All of the cells in a column refer to the same combo box, so if you filter out a value from the data source for one of them, you filter it out for all of them.
I'm currently trying to catch a CellChange event and check against all other currently-used values. If it was already used, I would put up a message saying as much and revert back to the old value. However, the value comes back as the previously-saved one, so... not helpful. About to see if I can use the "text" property.
Since you're using Infragistics, you could use an UltraDropDown which is bound to a DataTable (or something similiar) which you can add a "Selected" column in addition to a column holding the values you want to show.
As each value is selected (via AfterCellUpdate or AfterCellListCloseUp for instance), you could update the "Selected" column in that data source and use a column filter to only show items which haven't been marked as selected. That way as items are selected or removed, the contents of the drop-down would be automatically updated.
To clear the selected flag from the old value, you can use the BeforeCellUpdate event to access the cell's current value then perform a lookup on the data source bound to the UltraDropDown using that value to clear the flag.
Solved it:
The trick was to use BeforeCellUpdate whose BeforeCellUpdateEventArgs has a "NewValue" and a "Cancel" member. I just look through all of the items in the column to see if any of them match the new value. If one does, I notify the user and cancel the operation.
And that's it. Here's the code:
Private Sub myUltraWinGrid_BeforeCellUpdate(ByVal sender As Object, ByVal e As Infragistics.Win.UltraWinGrid.BeforeCellUpdateEventArgs) Handles myUltraWinGrid.BeforeCellUpdate
If e.Cell.Column.Key = "myColumn" Then
Dim newValue As Integer = CInt(e.NewValue)
For Each row As Infragistics.Win.UltraWinGrid.UltraGridRow In myUltraWinGrid.Rows
If row.Cells("myColumn") IsNot e.Cell _ 'So I'm not checking against the current cell
AndAlso CInt(row.Cells("myColumn").Value) = newValue Then
MsgBox("That value has already been used in this column")
e.Cancel = True
End If
Next
End If
End Sub

VB.Net ComboBox - Enums and Limiting Values Based on Selection in Another ComboBox

The project I'm working on makes extensive use of Enum's to hold unit symbols. Like this...
Public Enum AreaSym
unknown = 0
in2
mm2
End Enum
My Problems began when I realized that my Enum names didn't make good names for the drop downs on my ComboBoxes. I found and implemented a TypeConverter from this C# CodeProject http://www.codeproject.com/KB/cs/LocalizingEnums.aspx?msg=3746572 ... It allows you to assign the Enum Values friendly names in a .Resx file, and it overloads the GetValues function so that it returns the Enums friendly names from the .Resx file. This works well as I can then assign the combobox data source directly to the enum.
ComboBox1.DataSource = System.Enum.GetValues(GetType(AreaSym))
However, I realized that when using a Datasource in this manner, I have to manipulate the data source to create a change in the ComboBox. Such as, if I don't want to display unknown to the user, I'd need another way to load my ComboBoxes. This is when I decided to make a List(Of KeyValuePair(AreaSym, String))
Public Function AreaSymbols() As List(Of KeyValuePair(Of AreaSym, String))
AreaSymbols = New List(Of KeyValuePair(Of AreaSym, String))
AreaSymbols.Add(New KeyValuePair(Of AreaSym, String)(AreaSym.in2, "in²"))
AreaSymbols.Add(New KeyValuePair(Of AreaSym, String)(AreaSym.mm2, "mm²"))
Return AreaSymbols
End Function
This is great because now I can control exactly what goes into the combo box using the list.
ComboBox1.DataSource = UnitNameList.AreaSymbols
ComboBox1.DisplayMember = "Value"
ComboBox1.ValueMember = "Key"
However, I've found that using a DataSource has stopped me from doing two things.
When the form loads, I want the ComboBox itself to show as either empty with no text, or to show the Text I've input in the Text Property. Currently using the DataSource, it always is populated with the first item in the list.
I'd like to be able to easily limit the items in the list, based on the selection of items in another list. Classic example would be two ComboBoxes filled with the exact same values (1,2,3) & (1,2,3). When you choose 1 in ComboBox one, only (2,3) are available for selection in ComboBox 2.
I realize that I could probably easily do that if I was using Items, instead of a data source, I'm just not sure what the best way to do that would be because of my need to have the key, value pair of enums and strings...