在for,foreach语句中小心使用控件的SendToBack,BringToFront方
今天写了段VB。Net遍历控件的方法,乍一看没有什么问题,但结果却出人意料,control集合的元素没有遍历完,并且有重复的元素。 Public Sub SetControlLableAndPropertyFromXml(ByVal parent As Control) For Each subControl As Control In parent.Controls If subControl.HasChildren Then SetControlLableAndPropertyFromXml(subControl) End If If mShosaiConfig.ShosaiSetting.Items(subControl.Name) Is Nothing Then Continue For End If subControl.Text = mShosaiConfig.ShosaiSetting.Items(subControl.Name).LableText Dim editCtl = subControl.Parent.Controls.Item(mShosaiConfig.ShosaiSetting.Items(subControl.Name).CompoName) If Not editCtl Is Nothing Then If Not mShosaiConfig.ShosaiSetting.Items(subControl.Name).Editable Is Nothing Then editCtl.Enabled = mShosaiConfig.ShosaiSetting.Items(subControl.Name).Editable End If End If Next End Sub
最后发现是这一句editCtl.Enabled = mShosaiConfig.ShosaiSetting.Items(subControl.Name).Editable出了问题。editCtl是重写过的Combox控件,在OnEnabledChanged事件中用了,SendToBack和BringToFront方法。 Protected Overrides Sub OnEnabledChanged(ByVal e As System.EventArgs) MyBase.OnEnabledChanged(e) If Me.Enabled Then Me.m_lblComboText.Visible = False Else Me.m_lblComboText.Visible = True Me.SendToBack() Me.m_lblComboText.BringToFront() End If End Sub
SendToBack和BringToFront会改变控件的“Zindex“值来改变控件的显示层次,来看看他的内部实现: public void SendToBack() { if (this.parent != null) { this.parent.Controls.SetChildIndex(this,-1); } else if (this.IsHandleCreated && this.GetTopLevel()) { SafeNativeMethods.SetWindowPos(new HandleRef(this.window,this.Handle),NativeMethods.HWND_BOTTOM,3); } }
public virtual void SetChildIndex(Control child,int newIndex) { this.SetChildIndexInternal(child,newIndex); } ==》 internal virtual void SetChildIndexInternal(Control child,int newIndex) { if (child == null) { throw new ArgumentNullException("child"); } int childIndex = this.GetChildIndex(child); if (childIndex != newIndex) { if ((newIndex >= this.Count) || (newIndex == -1)) { newIndex = this.Count - 1; } base.MoveElement(child,childIndex,newIndex); child.UpdateZOrder(); LayoutTransaction.DoLayout(this.owner,child,PropertyNames.ChildIndex); } } 关键就是这句base.MoveElement(child,newIndex);会造成Controls内元素的重新排列。 法一:声明一个List<Control> lstControls,先遍历controls,把这些元素加到lstControls中,再对lstControls遍历,调用SendToBack方法。这种方法主要是避开对ControlConnection集合的遍历。 法二:已经知道要遍历控件name的场合,可以用parent.Controls.Find(controlName,True)来查找,再调用SendToBack方法。 也许还有其它更好方法,有待研究。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |