Search code examples
c#formattingobjectlistview

ObjectListView - Rows are formatted only after MouseOver on Items


I am in need of some assistance or advice/experience of someone else. Here is what I'm struggling with:

In my project an objectlistview olvDifference is used to visualize items (Type Conflict) of a list. So far I was able to add the Columns needed and format them properly. But the format provided with

private void ConflictFormatRow(object sender, 
BrightIdeasSoftware.FormatRowEventArgs e)
{
  Conflict conflict = (Conflict)e.Model;
  if (conflict == null) return;
  if (conflict.resolution == ConflictResolution.None) e.Item.BackColor = conflictColor;
  else if (conflict.resolution == ConflictResolution.UseMine) e.Item.BackColor = mineColor;
  else if (conflict.resolution == ConflictResolution.UseTheirs) e.Item.BackColor = theirsColor;
  else e.Item.BackColor = System.Drawing.Color.White;
  if(e.Model == olvConflictList.SelectedObject)
  {
    BrightIdeasSoftware.RowBorderDecoration a = new BrightIdeasSoftware.RowBorderDecoration();
    a.BorderPen.Color = Color.Black;
    a.BorderPen.Width = 3;
    a.CornerRounding = 0;
    a.FillBrush = Brushes.Transparent;
    e.Item.Decoration = a;
  }
  else
  {
    BrightIdeasSoftware.RowBorderDecoration b = new BrightIdeasSoftware.RowBorderDecoration();
    b.BorderPen.Color = Color.Transparent;
    b.BorderPen.Width = 0;
    b.CornerRounding = 0;
    b.FillBrush = Brushes.Transparent;
    e.Item.Decoration = b;
  }
}

In the constructor of the form (WFA), the AspectGetter is assigned and the objects to display are set.

Designer-Generated code equals the block below:

  // 
  // olvConflictList
  // 
  this.olvConflictList.AllColumns.Add(this.olvcConflictList);
  this.olvConflictList.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
  this.olvConflictList.CellEditUseWholeCell = false;
  this.olvConflictList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
        this.olvcConflictList});
  this.olvConflictList.Cursor = System.Windows.Forms.Cursors.Default;
  this.olvConflictList.FullRowSelect = true;
  this.olvConflictList.Location = new System.Drawing.Point(780, 90);
  this.olvConflictList.Name = "olvConflictList";
  this.olvConflictList.Size = new System.Drawing.Size(286, 489);
  this.olvConflictList.TabIndex = 18;
  this.olvConflictList.UseCellFormatEvents = true;
  this.olvConflictList.UseCompatibleStateImageBehavior = false;
  this.olvConflictList.View = System.Windows.Forms.View.Details;
  this.olvConflictList.FormatRow += new System.EventHandler<BrightIdeasSoftware.FormatRowEventArgs>(this.ConflictFormatRow);
  this.olvConflictList.SelectedIndexChanged += new System.EventHandler(this.olvDifferenceGroups_SelectedIndexChanged);
  // 
  // olvcConflictList
  // 
  this.olvcConflictList.AspectName = "";
  this.olvcConflictList.AutoCompleteEditor = false;
  this.olvcConflictList.AutoCompleteEditorMode = System.Windows.Forms.AutoCompleteMode.None;
  this.olvcConflictList.FillsFreeSpace = true;
  this.olvcConflictList.Groupable = false;
  this.olvcConflictList.HeaderCheckBoxUpdatesRowCheckBoxes = false;
  this.olvcConflictList.Hideable = false;
  this.olvcConflictList.IsEditable = false;
  this.olvcConflictList.MinimumWidth = 50;
  this.olvcConflictList.Searchable = false;
  this.olvcConflictList.Sortable = false;
  this.olvcConflictList.Text = "Conflicts";
  this.olvcConflictList.UseFiltering = false;
  this.olvcConflictList.Width = 283;

The only item in the olv has no BackGroundColor (White, default):

The only item in the olv has no BackGroundColor (White, default)

After starting the process, it is shown as one can see in the pic above, but I'd expect it to be initialized as in the pic below (after I hovered over it with my mouse the first time).

The only item in the olv has BackGroundColor conflictColor as assigned in the ConflictFormatRow:

The only item in the olv has BackGroundColor <code>conflictColor</code> as assigned in the ConflictFormatRow

Where do I need to improve my code? Any advices?


Solution

  • Well, I could figure it out myself. I took a look at the source of OLV and what i found out so far:

    In my case, the first row, here "Conflicts", was set to "Groupable=False", but the OLV itself was set to "ShowGroups=True". FormatRow is fired in PostProcessOneRow, which is called according to source (Version: 2.9.1.0) in following logic:

    protected virtual void PostProcessRows() {
            // If this method is called during a BeginUpdate/EndUpdate pair, changes to the
            // Items collection are cached. Getting the Count flushes that cache.
    #pragma warning disable 168
    // ReSharper disable once UnusedVariable
            int count = this.Items.Count;
    #pragma warning restore 168
    
            int i = 0;
            if (this.ShowGroups) {
                foreach (ListViewGroup group in this.Groups) {
                    foreach (OLVListItem olvi in group.Items) {
                        this.PostProcessOneRow(olvi.Index, i, olvi);
                        i++;
                    }
                }
            } else {
                foreach (OLVListItem olvi in this.Items) {
                    this.PostProcessOneRow(olvi.Index, i, olvi);
                    i++;
                }
            }
        }
    

    Since grouping failed, due to no groupable rows being present in OLV, the PostProcessOneRow in the if-body was not hit even once (foreach operated in "this.Groups" whichs count was 0).

    Set "ShowGroups=False", works like a charm now.