Skip to content

Color coding

The drilldown's grid uses conditional row coloring so that demand rows stand out as either covered (green) or shortfall (red), and informational rows are distinguished from real demand. The rules are implemented in gvMRPDetails_CustomDrawCell, which is registered as a CustomDrawCell handler on the drilldown's gridview after DisplayDrillDown returns.

Registration

Dim tempgv As MyGridView = PrimaryLayoutInterface.GridView
AddHandler tempgv.CustomDrawCell, AddressOf gvMRPDetails_CustomDrawCell

The handler runs once per cell as the grid renders, so the rules below are evaluated per-cell, not per-row.

Computing the minimum-quantity threshold

The threshold against which "demand" rows are evaluated is determined by the module's ItemLocationMinimumQuantityMode. There are four possible modes — three explicit and one that defers to the global MRP setting:

Mode Threshold
DefaultMRPSettings Whatever Instance.MRP.ItemLocationMinimumQuantityMode is currently set to (Zero, SafetyStock, or ReorderLevel)
Zero Constant 0
SafetyStock Value of safety_stk on the row
ReorderLevel Value of reorder_lvl on the row

The implementation:

Dim minLvl As Double = 0
Select Case MyData.ItemLocationMinimumQuantityMode
    Case CSD_1.enumItemLocationMinimumQuantityMode.DefaultMRPSettings
        Select Case Instance.MRP.ItemLocationMinimumQuantityMode
            Case CSD_MRP_1.ItemLocationMinimumQuantityModeEnum.Zero
                minLvl = 0
            Case CSD_MRP_1.ItemLocationMinimumQuantityModeEnum.SafetyStock
                minLvl = sender.GetRowCellValue(e.RowHandle, "safety_stk")
            Case CSD_MRP_1.ItemLocationMinimumQuantityModeEnum.ReorderLevel
                minLvl = sender.GetRowCellValue(e.RowHandle, "reorder_lvl")
        End Select
    Case CSD_1.enumItemLocationMinimumQuantityMode.Zero
        minLvl = 0
    Case CSD_1.enumItemLocationMinimumQuantityMode.SafetyStock
        minLvl = sender.GetRowCellValue(e.RowHandle, "safety_stk")
    Case CSD_1.enumItemLocationMinimumQuantityMode.ReorderLevel
        minLvl = sender.GetRowCellValue(e.RowHandle, "reorder_lvl")
End Select

MyData.ItemLocationMinimumQuantityMode is a property on COrdersCausingShortages.CSD_1 (the module's serial-data class).

Coloring rules

The handler reads mrp_ord_type from the row, then applies these rules in order:

Forecast rows

If mrpOrdType IsNot Nothing AndAlso mrpOrdType.ToUpper Like "FORECAST*" Then
    e.Appearance.Font = New Font(e.Appearance.Font, FontStyle.Bold)
End If

Any order type starting with FORECAST is rendered in bold. No background change.

ATP rows

If mrpOrdType Like "ATP*" Then
    e.Appearance.Font = New Font(e.Appearance.Font, FontStyle.Bold)
    e.Appearance.BackColor = Color.LightGray
ElseIf UCase(mrpOrdType) Like "*DEMAND*" Then
    ...
End If

Any order type starting with ATP (Available-To-Promise) is rendered bold with a light gray background, signaling these are virtual rows for capacity tracking rather than actual demand.

Demand rows

When mrp_ord_type contains the substring DEMAND (case-insensitive), the row is colored red or green based on whether the projected on-hand quantity is below or at/above the threshold.

The handler checks two columns independently — mrp_new_qty_il and mrp_new_qty_i — and applies coloring for whichever is visible:

If gv.Columns("mrp_new_qty_il") IsNot Nothing AndAlso gv.Columns("mrp_new_qty_il").Visible Then
    If sender.GetRowCellValue(e.RowHandle, "mrp_new_qty_il") < minLvl Then
        e.Appearance.BackColor = Color.Salmon
    ElseIf sender.GetRowCellValue(e.RowHandle, "mrp_new_qty_il") >= minLvl Then
        e.Appearance.BackColor = Color.LightGreen
    End If
End If

If gv.Columns("mrp_new_qty_i") IsNot Nothing AndAlso gv.Columns("mrp_new_qty_i").Visible Then
    If sender.GetRowCellValue(e.RowHandle, "mrp_new_qty_i") < minLvl Then
        e.Appearance.BackColor = Color.Salmon
    ElseIf sender.GetRowCellValue(e.RowHandle, "mrp_new_qty_i") >= minLvl Then
        e.Appearance.BackColor = Color.LightGreen
    End If
End If
Quantity vs threshold Background
Below threshold Salmon
At or above threshold Light green

Summary table

Row type Match Effect
Forecast mrp_ord_type upper-cased starts with FORECAST Bold font
ATP mrp_ord_type starts with ATP Bold font, light gray background
Demand (shortage) mrp_ord_type upper-cased contains DEMAND and projected qty < minLvl Salmon background
Demand (covered) mrp_ord_type upper-cased contains DEMAND and projected qty >= minLvl Light green background
Anything else Default appearance

Trigger refresh

DevExpress version 19.2 changed the lifecycle so CustomDrawCell is no longer triggered automatically on initial render. To work around this, RefreshData() is called at the end of OnDrillDown:

'Calling RefreshData() to trigger CustomDrawCell event (this used to be triggered automatically,
'but it has stopped working in DevExpress version 19.2)
tempgv.RefreshData()

Error handling

The whole handler body is wrapped in a Try / Catch with an empty catch — if any individual cell's coloring fails (typically because a referenced column is missing or a value is DBNull), the failure is swallowed and the cell renders in its default appearance.