RadComboBox – load even if value is missing in dataset

In developing a web application, I’ve frequently run into an issue with the dataset for a Radcombobox not being equal to historical data in the database.

For example, a table that stores equipment, with a column of employee numbers representing “assigned to”.

In the web application, I only want users to select Active employees so this is the contents of my Radcombobox dataset.

However, employees frequently transition to Inactive as they leave the company and there may still be equipment assigned to them. If they are marked Inactive and the Radcombobox is loaded for that record, it will error out with “Selection out of range Parameter name“.

Luckily I found this exact same situation on the Telerik forums, and the last post in the thread is what I needed.

In my case I have validation for empty Assigned Employees, so I modified the function to look like this:

protected void PreventErrorOnbinding(object sender, EventArgs e)
        {
            RadComboBox cb = sender as RadComboBox;
            cb.DataBinding -= new EventHandler(PreventErrorOnbinding);
            cb.AppendDataBoundItems = true;
 
            try
            {
                cb.DataBind();
                //cb.Items.Clear(); // Don't clear the combobox if the Databind is successful
            }
            catch (ArgumentOutOfRangeException)
            {
                cb.Items.Clear();
                cb.ClearSelection();
                RadComboBoxItem cbI = new RadComboBoxItem("", "");
                cbI.Selected = true;
                cb.Items.Add(cbI);
            }
        }

Then in my Radcombobox, I added “OnDataBinding="PreventErrorOnbinding".

Radgrid Context Menu on a button

With a Telerik RadGrid, the right-click context menu is not obvious to my users, so I needed to add a button that will perform the same function.

Unfortunately this isn’t a feature built into the RadGrid, and it took me a large amount of trial and error to get working.

Here’s what it looks like:

context

And here’s how to do it:

1. Add the following javascript to the script section of your page:

function showMenu(event, columnName) {
                var RadGrid = $find("<%=RadGrid1.ClientID %>");
                var gridId = RadGrid.get_id();
                var columns = $find(gridId).get_masterTableView().get_columns();
                for (var i = 0, length = columns.length; i < 1; i++) {
                    if (columns[i].get_uniqueName() == columnName) {
                        columns[i].showHeaderMenu(event, 75, 20);
                    }
                }
            }

2. Ensure you have an “OnItemDatabound” event for your RadGrid

3. In your “OnItemDatabound”, place the following code:

if (e.Item is GridHeaderItem)
            {
                ImageButton button = new ImageButton();
                button.ID = "ContextButton";
                button.Style.Add("padding-left", "5px");
                button.AlternateText = "ContextButton";
                button.ImageUrl = "../Images/Icons/contextMenu.png";
                button.OnClientClick = "showMenu(event, \"FullName\"); return false;";
                e.Item.Cells[2].Controls.Add(button);
            }

Where I have the “FullName” listed, replace that with an actual column name in your grid.

Now your button should show up in HeaderCell 2 (which for me was my first column) and operate exactly the same as the Right-Click context menu.

Skype for Business indicator using Particle Photon

LyncIndicator10I use Microsoft Skype for Business (formerly Lync) extensively at work and utilize a headset while doing so. This combined with the fact that I recently moved into an office at work as opposed to a cubicle led me to wanting a physical indicator of my Skype presence so that people walking in could know my status.

I briefly investigated pre-packed indicator devices such as the Embrava Blynclight and BusyLight but decided that shipping costs were too much and it would be fun to make my own.

Shortly after I stumbled upon a post by Jon Gallant where he built his own using a Particle Photon and called it Beakn. This sounded like it would be exactly what I wanted, and so I set about building one.

Estimating the placement of the built-in LED
Estimating the placement of the built-in LED

Step 1 – what will it look like?

I thought about building it out of Lego, but my wife persuaded me that it wouldn’t be professional enough. I had seen a forum post where someone took the Embrava Blynclight and stuck it in a picture frame, and this really appealed to me.

I bought a Photon, scrounged up a decent looking frame, and got ready.

Step 2 – Build the prototype

I used sandpaper to thin out the mat so that the LED would shine through. I wasn’t very circular which may have had an impact on how unsatisfied I was with this design.

LyncIndicator2LyncIndicator3

 

 

 

 

 

 

 

 

 

I had a small USB device charger that I used for my proto-type. A little bit of duct tape and I was ready to go. LyncIndicator4

 

Step 2a – Get the Photon on the network

I had a lot of trouble getting the Photon connected to my Wifi. It worked at home no problem, but when I brought it to work I couldn’t get it to connect. And then all of a sudden something happened where it wouldn’t boot at all but instead gave me SOS codes.

Through a support ticket with Particle I was finally able to get the device back online by flashing a new firmware. Then I discovered that the Photon uses non-standard ports for cloud communication rather than HTTP or HTTPs. Outbound traffic is restricted in my work network and so that was the source of connectivity issues.

Once all that was sorted, getting the code as documented by Jon Gallant was very easy and worked like a charm.

It's alive! And apparently away from the keyboard.
It’s alive! And apparently away from the keyboard.

Step 3 – Better batteriesLyncIndicator6

I shameless tore apart an old broken toy from the basement to make use of a battery pack. Unfortunately the best I could find was a 3xAAA pack with a power switch. More duct tape ensued and I wired positive (red) to the VIN pin and black to GND pin on the Photon.

This worked well at first, but when I took it to work and attempted to use it for real, the Photon would die after 10 minutes or so. I knew the batteries were brand new and not dead yet, so I posted a question to the Particle forums.

It turns out that 3xAAA is likely not providing enough voltage for the Photon when it’s constantly running it’s Wifi. I needed more power!

 

Step 4 – New batteries and changing LEDs

Through my prototype and AAA testing I had determined that the indicator light at the bottom of the frame just wasn’t going to do. It wasn’t bright enough, and didn’t match up well with the “Legend” that I planned to put in the actual frame.

This change let me use the breadboard that came with the Photon, and so I spent some time learning how to use it and the power rails. I highly recommend reading this Sparkfun tutorial.

LyncIndicator7

Next I went back through some of Jon Gallant’s older posts and found his designs for individual LEDs. I decided I was going to put individual LEDs right in the middle of my legend, and again used a Sparkfun tutorial to learn about that.

Back into the basement to break more toys! I managed to find a good green and red LED but a poor quality yellow was all I could produce.

I went to Value Village and found a cheap toy that took 4xAA batteries and tore that apart for this project too.

I didn’t take good pictures of the final build process unfortunately, but it is fairly clear from this photo which I’ll walk through for those just learning like I am.

LyncIndicator8

Power comes in from the batteries on the red wire to the positive rail on the breadboard. I have wires connecting the right-hand rail to ensure the circuit is complete there.

The next red wire on the left side goes from the power rail to the row with the VIN pin on the Photon. A black wire in the next row down takes GND pin from the Photon to the negative rail, completing the circuit.

On the other side, I sort of lost my color coordination because I got tired of stripping wires (I was using leftover 3 strand thermostat wire so all 3 colors were bundled together).

Pins 4, 5, and 6 on the Photon are wired to the positive ‘anode’ side of each LED. The negative cathode side is wired with the white cables, each going to a row with a resistor before completing on the negative power rail.

Looking at this photo now it almost seems like I have the resistor in the wrong place, as I thought it should be in between the positive source of the Photon pin, and the anode on the LED. But according to this it doesn’t really matter.

Here’s a close-up of the breadboard:

LyncIndicator9

To get this setup to work, I had to modify the Beakn code because of the pins on the Photon I decided to use, and it didn’t have a status for “FreeIdle” when I locked my PC. The code I used in the cloud IDE is reproduced at the bottom of this post.

Once I had this all wired up, I used hooks and fishing wire, and hung it in my office window:

LyncIndicator10

Overall I’m very happy with the results, but there’s room for improvement.

Step 5 – What’s next

Once I got this running, it only lasted 2 1/2 work days before the batteries died. Based on feedback from my particle forum post, I need a capacitor to smooth out the power draw and ideally a way to turn off the Wifi on the Photon and only check for status changes at intervals.

Neither of those are easily accomplished (because it’s hard to source a single capacitor and I have no soldering iron to break more toys with), so instead I’m going to use rechargeable batteries and attempt to build myself a solar charge mechanism using lawn lights. A future post will address that addition if I can ever get it to work.

 

Code:

int red = 5;
int yellow = 4;
int green = 6;
void setup() 
{
  Spark.function("setStatus", setStatus);
  pinMode(red, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(green, OUTPUT);
  for(int i = 5; i <= 7; i++)
  {
      digitalWrite(i, HIGH);
      delay(250);
      digitalWrite(i, LOW);
      delay(250);
  }
  reset();
}
void loop() 
{}
void reset()
{
  digitalWrite(red, LOW);
  digitalWrite(yellow, LOW);
  digitalWrite(green, LOW); 
}
int setStatus(String status)
{
  reset();  
  if(status == "Busy" || status == "DoNotDisturb"){
    digitalWrite(red, HIGH);
  }else if(status == "Away" || status == "TemporarilyAway" || status == "FreeIdle"){
    digitalWrite(yellow, HIGH);
  }else if (status == "Free"){
    digitalWrite(green, HIGH);
  }
  return 1;
}

Expand Linux LVM with free space from Hyper-V

This page is a bit of an update from my last post on expanding Linux volumes.

The scenario is a pre-existing VHDX file that is mounted within a Debian virtual machine, which has used LVM to create volumes.

Now we want to expand that VHDX file, and then extend the pre-existing volumes without spanning new partitions.

  1. Expand the disk in the Hypervisor
  2. Reboot the VM to recognize the change (there’s specific commands to do this as well)
  3. Run parted on your disk: parted /dev/sdb
  4. Change display unit to sectors: unit s
  5. Print current partition table and note the start sector for your partition: p
  6. Delete your partition (won’t delete the data or filesystem): rm <number>
  7. Recreate the partition with the starting sector from step 5 above: mkpart primary <start> -1
  8. Exit parted: quit
  9. Reboot the VM to recognize the new partition size
  10. Type the following to resize the physical volume: pvresize /dev/sdb1
  11. Now you can re-allocate size to a logical volume by using the following (this adds 20G to existing size): lvextend -L+20G /dev/volumegroup1/mylogicalvolume
  12. For any logical volume that you resized, you need to extend the ext4 partition: resize2fs /dev/volumegroup1/mylogicalvolume

SqlDataSource Delete Parameters and BoundFields

I recently ran across an issue that took a while to resolve, but really shouldn’t have.

I have an SqlDataSource which I’m purposefully using an UPDATE statement for in the DeleteCommand, like this:

DeleteCommand="UPDATE [dbo].[UDIC_EquipInventory]
                        SET [Status] = '6'
                            ,[AssignedTo] = ''
                            ,[RetiredDate] = GetDate()
                            ,[LastEditDate] = GetDate()
                            ,[LastOperator] = @LastOperator
                         WHERE UnitID = @unitid"

I have both the parameters there included properly like this:

<DeleteParameters>
            <asp:Parameter Name="unitid" DbType="String" />
            <asp:SessionParameter Name="LastOperator" SessionField="SignedInEmployeeId" DbType="String" />
 </DeleteParameters>

 

However every time I tried to use the DeleteCommand on my Telerik RadGrid tied to this datasource, I received the error “Must declare the scalar variable @LastOperator”.

 

It turns out according to this MSDN article on Delete Parameters, a parameter CANNOT be the same name as a boundfield representing this column.

I simply changed the parameter name in my query and DeleteParameters sections, and now it works!