Hi,
Within a WinForms UlraGrid, I am looking for a means (via code) to alter the appearance of an entire row, whenever a targeted column value meets a certain condition. For example, I already know that I can target the respect cell via the ConditionValueAppearance. The closest I could find to what might work is the ConditionAppearanceRow Class. Unfortunately you don't provide any code snippets to demonstrate how this class is hooked up with a given DisplayLayout Band.
In any case, I need this capability through code, so I can set the row appearance on the fly. If there is another way to do this, I am all ears.
Thanks,
Lacy
Hi Lacy,
Conditional Appearances are really useful for setting things up at Design-time. But at run-time, they actually require more code than neccessary and it's much easier to do things a different way.
I recommend using the InitializeRow event of the grid. This event is specifically designed to help you with situations just like this one where you want to color the row based on a value inside that row. All you do is handle the event, examine the row and it's cells and then set the Appearance properties on the row to suit your needs.
Hi Mike,
I implemented a conditional appearance in my initialize row event (changes backcolor based on value), but now I am seeing a slower response time when I change the rowfilter on the dataview the ultragrid is bound to. Do you have any performance tips?
Thanks,Kelly
Hi Kelly,
I would probably recommend creating the appearance as part of the grid.DisplayLayout.Appearances collection. Which means you create the appearances for each grid.
You can try creating the appearance outside the grid and sharing it amongst all of the grids, but I think there might be a problem with that because of the ImageList. The Appearance needs the grid to get to the grid's ImageList in order to get images from an ImageList. Even if these are not being used, it might cause an error if you try to use the same Appearance object in more than one grid. You can try it out, though. If there is a problem, you will get an exception when the grid's try to paint. If there's no exception and both grids display okay, then I would say it's probably safe to use the same appearance for all grids.
Hi Mike,Creating global appearances did work. I tried to implement your suggestions, so does this now look more efficient?
Dim LightYellowApp, LightGreenApp, LightRedApp, LightGreyApp As New AppearanceLightYellowApp.BackColor = Me.LightYellowLightGreenApp.BackColor = Me.LightGreenLightRedApp.BackColor = Me.LightRedLightGreyApp.BackColor = Me.LightGreyRowName.Cells(MyCol.Key).Appearance = Me.LightRedAppPrivate Sub UltraGrid_InitializeLayout(sender, e) For Each MyCol As UltraGridColumn In .UltraGrid.DisplayLayout.Bands(0).Columns If IsNumeric(MyCol.Key) = True Then .UltraGrid.DisplayLayout.Bands(0).Columns(MyCol.Key).CellAppearance = Me.LightYellowApp End If NextEnd SubPrivate Sub UltraGrid_InitializeRow(sender, e) AddConditionalFormatting(e.Row, False)End SubPrivate Sub AddConditionalFormatting(ByRef RowName As UltraGridRow, ByVal IsAssignmentsGrid As Boolean) Dim CellValue As Decimal For Each MyCol As UltraGridColumn In RowName.Band.Columns If IsNumeric(MyCol.Key) Or MyCol.Key = "Total FTE" Then If IsAssignmentsGrid = True AndAlso MyCol.Key <> "Total FTE" AndAlso RowName.Cells(MyCol.Index + 2).Value = "Y" Then RowName.Cells(MyCol.Key).Appearance = Me.LightGreyApp Else ' not assignments grid, or is and it is the total fte column If (Not RowName.GetCellValue(MyCol) Is DBNull.Value) AndAlso RowName.GetCellValue(MyCol) <= 0 Then CellValue = RowName.GetCellValue(MyCol) If CellValue < 0 Then RowName.Cells(MyCol.Key).Appearance = Me.LightRedApp End If Else ' value > 0 or is null RowName.Cells(MyCol.Key).Appearance = Me.LightGreenApp End If End If End If NextEnd Sub
Thank you again for your time and assistance,Kelly
Yes, this looks a lot more efficient to me. The only minor inefficiency I see here is that you are calling GetCellValue with for the same column several times. It would probably be metter to call it once and store the value. But that's a very small thing and probably won't make any noticable difference.
Is there any chance that conditional formatting may be applied simply by DataBinding?
Let's say the datagrid is bound to a BindingList<MyDataObject>
couldn't the MyDataObject expose a Color property on which to bind the forecolor property of the cell?
If so, how would you declare the databinding?
There's no way to "bind" a color to a cell or a row. But you could accomplish what you want here very easily by using the InitializeRow event.
Hi Gregory,
Sorry, I got a little mixed up there. I thought we added a SelectedAppearance to the row, but it's actually only available on the cell.
Anyway, I think you can achieve essentially the same thing using the row.CellAppearance, instead of row.Appearance. CellAppearance will override the selected appearance, I think.
If I am wrong, then the alternative would be to loop through cells in the row and apply the appearance to the cell.Appearance and possibly also the cell.SelectedAppearance and maybe also the cell.ActiveAppearance if you want.
Yes. In addition to setting the Appearance on the row, you can set the SelectedAppearance, also. This was added a couple of years back, so if you are using a very old version of the controls, it might not be available. In that case, it's much more difficult to handle and you would have to use a DrawFilter.
Hey Mike,
I have my grid row backcolor turning red thanks to your posts, but if my red row happens to be the first row in the grid when that row is the selected row the selected row color of orange seems to take precidence over the red color. As soon as I click off of that row then I can see the red backcolor. Is there a way to force the red backcolor to override the selected row color?
Gregory
Normal 0 false false false EN-US ZH-CN X-NONE
e.Row.Update(); has done the trick
Many Thanks Boris.
Ganesh.