2011-06-28 36 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