Winforms:FlowLayoutPanel的Layout事件期间获得的位置属性don';t反映更新后的布局.
本文关键字:布局 更新 don 位置 事件 Layout FlowLayoutPanel Winforms 属性 | 更新日期: 2024-10-24 21:34:38
我正在为包含UserControls的FlowLayoutPanel使用非自动VScrollBar控件。
我需要弄清楚FlowLayoutPanel中的任何控件是否位于其客户端区域之外。我想使用这些信息来确定VScrollBar是否可见。我在FlowLayoutPanel的Layout事件处理程序方法中放入了以下代码:
bool lookingForControl = true;
bool controlBelowClientArea = false;
int controlIndex = 0;
int controlBottomPos;
Control[] controlsTemp = new Control[leftFlowLayoutPanel.Controls.Count];
leftFlowLayoutPanel.Controls.CopyTo(controlsTemp, 0);
while (lookingForControl) {
controlBottomPos = controlsTemp[controlIndex].Bottom +
controlsTemp[controlIndex].Margin.Bottom;
debugTextBox.AppendText("Bottom position of control " + controlIndex +
": " + controlBottomPos + "'n");
if (controlBottomPos > leftFlowLayoutPanel.ClientSize.Height) {
controlBelowClientArea = true;
lookingForControl = false;
}
controlIndex ++;
if (controlIndex == leftFlowLayoutPanel.Controls.Count) {
lookingForControl = false;
}
}
以下是向控件2添加四个连续控件所得到的debugTextBox的输出,控件2的AutoSize属性设置为true。控件2包含在leftFlowLayoutPanel中,通过单击其中包含的按钮将控件添加到其中:
- 表单刚刚加载:
- 控件的底部位置0:3
- 控件底部位置1:128
- 控件底部位置2:253
- 添加的第一个控件:
- 控件的底部位置0:3
- 控件底部位置1:128
- 控件底部位置2:253
- 添加的第二个控件:
- 控件的底部位置0:3
- 控件底部位置1:226
- 控件底部位置2:351
- 添加了第三个控件:
- 控件的底部位置0:3
- 控件底部位置1:324
- 控件底部位置2:449
- 添加了第四个控件:
- 控件的底部位置0:3
- 控件底部位置1:422
- 控件底部位置2:547
添加第四个控件后,控件的底部之一超过其容器的ClientArea的高度(458),controlBelowClientArea被分配值true。
问题很明显:在Layout事件期间,我从FlowLayoutPanel获得的值比表单的最终布局落后一步。在我将第四个控件添加到控件1后,它的底部位置应该是520。
我想到的唯一答案是Layout事件发生在所有属性的值都正确设置之前。也许它是在执行任何内置布局逻辑之前调用的。如果是这样的话,有没有更适合我处理的事件?
我想到的唯一答案是Layout事件发生了在正确设置所有属性的值之前
如果这确实是问题所在,您可以尝试以下解决方法。
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Sign up for the FlowLayoutPanel Layout event.
// When that event occurs, run your layout logic
// using BeginInvoke to give the control a chance
// to "settle down".
//
this.flowLayoutPanel1.Layout += delegate { this.BeginInvoke( ( Action )this.DoYourWorkHere ); };
}
void DoYourWorkHere()
{
//TODO: do your custom layout logic here.
}
}
}
我尝试了一个简单的应用程序,在这个应用程序中,我测试按钮是否在FlowLayoutPanel的区域中。如果为true,它会显示一条文本框消息"out",它可以工作:
private void button2_Click(object sender, EventArgs e)
{
Button btn = new Button();
flowLayoutPanel1.Controls.Add(btn);
if((btn.Size.Height + btn.Location.Y) > (flowLayoutPanel1.Size.Height + flowLayoutPanel1.Location.Y))
{
textBox1.Text = "out";
}
}
尝试这个
while (lookingForControl) {
controlBottomPos = controlsTemp[controlIndex].Size.Height +
controlsTemp[controlIndex].Location.Y ;
debugTextBox.AppendText("Bottom position of control " + controlIndex +
": " + controlBottomPos + "'n");
if (controlBottomPos > leftFlowLayoutPanel.Size.Height + leftFlowLayoutPanel.Location.Y) {
controlBelowClientArea = true;
lookingForControl = false;
}
controlIndex ++;
if (controlIndex == leftFlowLayoutPanel.Controls.Count) {
lookingForControl = false;
}
}
为了获得最新的属性值,我使用以下代码从Layout事件处理程序方法调用引用包含原始代码的方法的委托。
private void leftFlowLayoutPanel_Layout(object sender, LayoutEventArgs e) {
if (this.IsHandleCreated) {
this.BeginInvoke((Action)this.OriginalLayoutCode);
}
}
我使用了IsHandleCreated检查来避免可能出现的InvalidOperationException。