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.