winforms ControlCollection事件?/ OnControlRemoved(批量/清除?)

7fhtutme  于 2023-06-24  发布在  其他
关注(0)|答案(2)|浏览(82)

我们正在使用FlowLayoutPanel的自定义实现,因为.net Framework提供的实现非常慢。
因此,无论何时添加/删除控件,我们都会分别处理OnControlAddedOnControlRemoved中坐标的增量重新计算。
现在,如果flowLayoutPanel.Controls.AddRange(...)flowLayoutPanel.Controls.clear()被调用,则OnControlAddedOnControlRemoved分别被调用多次。
Clear()的情况下,我们所要做的就是将4个变量设置为0,而不是为每次删除重新计算位置。我们有一个方法flowLayoutPanel.ClearControls(),但现在面临着外部库的问题,它直接调用flowLayoutPanel.Controls.Clear(),因为它显然不知道“我们的”实现。
不幸的是,OnControlRemovedControlEventArgs不提供任何信息,如果它是一个单一的删除,或调用已发出的Clear()
因此,我正在寻找一种方法,能够判断是否调用了ControlCollection.Clear()
目前看来,除了扩展ControlCollection类,在Clear()上实现一个适当的事件并从我们的FlowLayoutPanel订阅该事件之外,没有其他方法。但在走这条路之前,只是想问,也许有某种通用的CollectionChangedObserver可以附加到flowLayoutPanel.Controls-集合和.Remove().Clear()之间的区别?

u2nhd7ah

u2nhd7ah1#

在花了相当长的时间查看源代码之后,除了扩展ControlCollection类并添加像“ClearStarts”和“ClearEnds”这样的事件之外,还有其他方法,这样您就可以忽略中间的以下删除操作,只对ClearEnds进行操作。

gajydyqb

gajydyqb2#

因此,我现在创建了自己的ControlCollection实现,并在FlowLayoutPanel实现中使用了它。Thx到专用方法Control.ControlCollection.CreateControlsInstance,实际上很容易“挂钩”,而不会对原始实现造成太多干扰:

public class ExtendedControlCollection : ControlCollection
{
    public event EventHandler OnBeforeClear;
    public event EventHandler OnAfterClear;

    public ExtendedControlCollection(Control owner) : base(owner)
    {
        
    }

    public override void Clear()
    {
        OnBeforeClear?.Invoke(this, new EventArgs());
        base.Clear();
        OnAfterClear?.Invoke(this, new EventArgs());
    }
}

以及我们FlowLayoutPanel的相关部分:

private Boolean IsClearingControls { get; set; } = false;
    private EventHandler OnBeforeClearHandler = null;
    private EventHandler OnAfterClearHandler = null;
    ...
    protected override Control.ControlCollection CreateControlsInstance()
    {
        this.OnBeforeClearHandler = (object o, EventArgs e) =>
        {
            this.IsClearingControls = true;
        };

       this.OnAfterClearHandler = (object o, EventArgs e) =>
        {
            this.FlowPositionX = 0;
            this.FlowPositionY = 0;
            this.FlowingHeight = 0;
            this.IsClearingControls = false;
        };

        ExtendedControlCollection ecc = new ExtendedControlCollection(this);
        ecc.OnBeforeClear += this.OnBeforeClearHandler;
        ecc.OnAfterClear += this.OnAfterClearHandler;

        return ecc;
    }
    ....

    protected override void OnControlRemoved(ControlEventArgs e)
    {
        base.OnControlRemoved(e);
        if (!this.IsClearingControls)
        {
            //Recalculate positions for Controls based on removed control
            //else: Do nothing, clearing is handled in OnAfterClear() Listener.
        }
    }
    ...
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (this.OnBeforeClearHandler != null)
            {
                ((ExtendedControlCollection)this.Controls).OnBeforeClear -= this.OnBeforeClearHandler;
                this.OnBeforeClearHandler = null;
            }

            if (this.OnAfterClearHandler != null)
            {
                ((ExtendedControlCollection)this.Controls).OnAfterClear -= this.OnAfterClearHandler;
                this.OnAfterClearHandler = null;
            }
        }

        base.Dispose(disposing);
    }

相关问题