我创建了一个用户控件,并将其添加到网格中。
BuildingBlock m_Bblock = new BuildingBlocks.BuildingBlock(2, 2);
m_grid.Children.Add(m_Bblock);
我的BuildingBlock的构造函数将输入和输出按钮的数量作为输入,它们都是用户控件。 在构造函数内部,我具有:
for (int kk = 0; kk < NumIn; ++kk)
{
InButton inbtn = new InButton();
inbtn.m_Button_Click += Button_In_Click;
InStackPanel.Children.Add(inbtn);
AllInBtn.Add(inbtn);
}
以及类似的OutButton代码。
我需要了解第一个OutButton在网格上的位置信息,所以我使用了:
OutButton btn = m_Bblock.AllOutBtn[0];
Point pt = btn.TransformToAncestor(m_grid).Transform(new Point(0, 0));
这会导致错误(“指定的Visual并非此Visual的前身”)。我认为这是由于系统尚未“创建” OutButton,因为:
Point pt = m_Bblock.TransformToAncestor(GridDropAccept).Transform(new Point(0, 0));
有效并且:
OutButton btn = m_Bblock.AllOutBtn[0];
Point pt = btn.TransformToAncestor(m_grid).Transform(new Point(0, 0));
如果以后再调用此代码(例如,在创建事件之后通过单击按钮)会起作用。
为什么会这样?如何刷新OutButton的“创建”,以便可以将其用于自己的目的?
答案 0 :(得分:0)
为什么会这样?
因为构造函数执行时尚未在屏幕上呈现控件。这发生在稍后的阶段。
您可以将代码放入Loaded
事件处理程序中,该事件处理程序将在控件准备好进行交互时触发:
this.Loaded += (s, e) =>
{
OutButton btn = m_Bblock.AllOutBtn[0];
Point pt = btn.TransformToAncestor(m_grid).Transform(new Point(0, 0));
};
答案 1 :(得分:0)
感谢mm8和GazTheDestroyer对理解初始化和加载之间的区别的建议。
在我的情况下,调度员(Is there a "All Children loaded" event in WPF)是更好的解决方案:
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => {
prova(); }));
具有:
void prova ()
{
OutButton btn = m_Bblock.AllOutBtn[0];
Point pt = btn.TransformToAncestor(GridDropAccept).Transform(new Point(0, 0));
}
那对我来说就像一种魅力。