2011-06-28 25 views
2

我有一堆ElementHosts,我加载到我的表单上。发生这种情况时,元素主机全部以黑色背景显示。如果我将另一个控件放在前面,然后关闭另一个控件,则ElementHosts会正常重绘。一些google搜索后,我发现,如果我子类ElementHost的,做这在构造ElementHost布局问题

using (CreateGraphics()) { } 

的ElementHosts都绘制好的背景....但是,他们需要约300ms的每个元素的主机出现在表单......并且它们按顺序出现......所以就像看着表单布局一样......我手动地调用了SuspendLayout和ResumeLayout,但这不会改变结果。

这只是Windows窗体集成bugginess?还是有什么我可以做的,这使得控制正确显示并以合理的速度?

谢谢。

UPDATE:我能够用非常简单的代码来重现问题:

public partial class TestControl2 : UserControl 
    { 
     public TestControl2() 
     { 
      InitializeComponent(); 
     } 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 

     // deferring load with the BackgroundWorker seems to be related to the problem here... 
     var bw = new BackgroundWorker(); 
     bw.DoWork += delegate { Thread.Sleep(2000); }; 
     bw.RunWorkerCompleted += delegate 
     { 
      int x = 0; 
      int y = 0; 
      for (int i = 0; i < 20; i++) 
      { 
       var control = new Panel(); 
       control.Width = 200; 
       control.Height = 80; 
       control.Controls.Add(new ElementHost { Child = new System.Windows.Controls.Label { Content = @"Hello" }, Dock = DockStyle.Left, Size = new System.Drawing.Size(75, 23) }); 
       control.Controls.Add(new ElementHost { Child = new System.Windows.Controls.Button { Content = @"button" }, Dock = DockStyle.Fill }); 
       var uc2 = new UserControl(); 
       uc2.Controls.Add(control); 
       control.Dock = DockStyle.Fill; 
       uc2.Left = x; 
       uc2.Top = y; 
       x += control.Width + 10; 
       // adding using (uc2.CreateGraphics()) {} fixes the problem but slows down the load so it looks like each UserControl is being added one at a time 
       panel1.Controls.Add(uc2); 
      } 
     }; 

     bw.RunWorkerAsync(); 
    } 
    } 

回答

2

圣sh * t,我终于得到它的工作。我试图从谷歌代码(有一对夫妇的来源.... How do I suspend painting for a control and its children? ...命名一个):

private const int WM_SETREDRAW = 0x000B; 

    public static void Suspend(this Control control) 
    { 
     Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero, 
      IntPtr.Zero); 

     NativeWindow window = NativeWindow.FromHandle(control.Handle); 
     window.DefWndProc(ref msgSuspendUpdate); 
    } 

    public static void Resume(this Control control) 
    { 
     var wparam = new IntPtr(1); 
     Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam, 
      IntPtr.Zero); 

     NativeWindow window = NativeWindow.FromHandle(control.Handle); 
     window.DefWndProc(ref msgResumeUpdate); 

     control.Invalidate(); 
    } 

它并没有解决我的问题,并给我留下了黑色搞砸背景。 ..但我想尝试添加以下的恢复方法:

 public static void Resume(this Control control) 
     { 
      control.Visible = false;     
      // existing code above.... 
      control.Visible = true; 
     } 

和BAM!有用。

+0

您是否尝试过在您的控件中调用“刷新”而不是隐藏它并再次显示它 –

+0

是的。不起作用。 – Jeff

+1

@Jeff:任何方式来解决调整大小相同的问题? http://stackoverflow.com/questions/29277844/elementhost-flickers-black-borders-on-resize/我绝望了。 –

0

虽然没有直接回答你的问题,你有没有尝试添加只有一个ElementHost的(因此只有一个WPF UserControl)到您的WindowsForm。

如果您创建一个WPF UserControl,它可以聚合所有您的WPF UserControl,那么您可以实现此目的。 这是一个可行的解决方案吗? t可能会减少 或者您是否必须将Windows窗体控件与wpf控件混合?

+0

如果您尝试上述示例并将i <10替换为i <1,则应该看到这样做不起作用,并且仍然在ElementHost中产生了一个错误的正文 – Jeff

+0

关于第二个问题,我不必本身,但我试图从Windows窗体将我们的应用程序迁移到WPF,并希望保持一致的外观和感觉。 – Jeff