C# objectlistview undefined offset in cell editor

624 views Asked by At

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

2

There are 2 answers

2
murzagurskiy On BEST ANSWER

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;
            }
        }
//...
0
Rev On

The issue still exists in OLV v2.9.1. I worked around it slightly different than muzagursiy did.

        olv.CellEditStarting += (sender, args) =>
        {
            // Left align the edit control
            args.Control.Location = args.CellBounds.Location;

            // Readjust the size of the control to fill the whole cell if CellEditUseWholeCellEffective is enabled
            if (args.Column.CellEditUseWholeCellEffective)
            {
                args.Control.Size = args.CellBounds.Size;
            }

        };