Search code examples
c#textboxcomponentsobjectlistviewtreelistview

C# objectlistview undefined offset in cell editor


I use TreeListView component from ObjectListView library. I make cell values editable and when i double click on them TextBox will appear with odd offset. I want to remove this offset, but how?

before start editing enter image description here

after start editing enter image description here

As you can see first row, second column ("My new device"), TextBox is appeared with offset.

P.S. Editing work as expected. Only offset is annoying me

P.P.S. As you can see the offset depends of first column offset. How i can change it to zero? enter image description here


Solution

  • After long searches i found solution!

    Source code of OLV, ObjectListView.cs

    public virtual void StartCellEdit(OLVListItem item, int subItemIndex) {
                OLVColumn column = this.GetColumn(subItemIndex);
                Control c = this.GetCellEditor(item, subItemIndex);
                Rectangle cellBounds = this.CalculateCellBounds(item, subItemIndex);
                c.Bounds = this.CalculateCellEditorBounds(item, subItemIndex, c.PreferredSize);
    
                // Try to align the control as the column is aligned. Not all controls support this property
                Munger.PutProperty(c, "TextAlign", column.TextAlign);
    
                // Give the control the value from the model
                this.SetControlValue(c, column.GetValue(item.RowObject), column.GetStringValue(item.RowObject));
    
                // Give the outside world the chance to munge with the process
                this.CellEditEventArgs = new CellEditEventArgs(column, c, cellBounds, item, subItemIndex);
                this.OnCellEditStarting(this.CellEditEventArgs);
                if (this.CellEditEventArgs.Cancel)
                    return;
    
                // The event handler may have completely changed the control, so we need to remember it
                this.cellEditor = this.CellEditEventArgs.Control;
    
                this.Invalidate();
                this.Controls.Add(this.cellEditor);
                this.ConfigureControl();
                this.PauseAnimations(true);
            }
    

    I saw CellEditEventArgs contains Control, that drawed in area named Bounds.

    This function in the source file append offset to control's bounds:

    protected Rectangle CalculateCellEditorBoundsStandard(OLVListItem item, int subItemIndex, Rectangle cellBounds, Size preferredSize) {
                if (this.View == View.Tile)
                    return cellBounds;
    
                // Center the editor vertically
                if (cellBounds.Height != preferredSize.Height)
                    cellBounds.Y += (cellBounds.Height - preferredSize.Height) / 2;
    
                // Only Details view needs more processing
                if (this.View != View.Details) 
                    return cellBounds;
    
                // Allow for image (if there is one). 
                int offset = 0;
                object imageSelector = null;
                if (subItemIndex == 0)
                    imageSelector = item.ImageSelector;
                else {
                    // We only check for subitem images if we are owner drawn or showing subitem images
                    if (this.OwnerDraw || this.ShowImagesOnSubItems)
                        imageSelector = item.GetSubItem(subItemIndex).ImageSelector;
                }
                if (this.GetActualImageIndex(imageSelector) != -1) {
                    offset += this.SmallImageSize.Width + 2;
                }
    
                // Allow for checkbox
                if (this.CheckBoxes && this.StateImageList != null && subItemIndex == 0) {
                    offset += this.StateImageList.ImageSize.Width + 2;
                }
    
                // Allow for indent (first column only)
                if (subItemIndex == 0 && item.IndentCount > 0) {
                    offset += (this.SmallImageSize.Width * item.IndentCount);
                }
    
                // Do the adjustment
                if (offset > 0) {
                    cellBounds.X += offset;
                    cellBounds.Width -= offset;
                }
    
                return cellBounds;
            }
    

    We can see, that offset appending to every cell (not only first). Also we can se, that CellEditEventArgs contains CellBounds.

    So we can just reset Control.Bounds to CellBounds value:

    //...
    dataTreeView.CellEditStarting += DisableInputValueForCollections;
    //...
            private static void DisableInputValueForCollections(object sender, CellEditEventArgs e)
            {
                RemoveExtraOffsetForNotFirstColumnInputControl(e);
                var node = e.RowObject as DataTreeNode;
    
                if (node != null && e.Column.AspectName == "Value")
                {
                    if (node.IsContainer()) e.Cancel = true;
                }
            }
    //...
    private static void RemoveExtraOffsetForNotFirstColumnInputControl(CellEditEventArgs e)
            {
                if (e.Column.AspectName != "Name")
                {
                    e.Control.Bounds = e.CellBounds;
                }
            }
    //...