ElementHost Проблемы с макетом
У меня есть куча ElementHosts, которые я загружаю в форму. Когда это происходит, все элементы хоста отображаются с черным фоном. Если я перенесу другой элемент управления на передний план, а затем закрою другой элемент управления, ElementHosts будет перекрашен в обычном режиме. После некоторого поиска в Google, я обнаружил, что если я подкласс ElementHost и сделать это в конструкторе
using (CreateGraphics()) { }
ElementHosts все нарисованы с хорошим фоном.... НО, они требуют около 300 мс на хост элемента, чтобы появиться в форме... и они появляются последовательно... так что это похоже на просмотр формы, выложенной... У меня есть, конечно, вызывается SuspendLayout и ResumeLayout вручную, но это не меняет результат.
Это просто ошибка интеграции с Windows Forms? Или я могу что-то сделать, чтобы элементы управления выглядели правильно и с разумной скоростью?
Благодарю.
ОБНОВЛЕНИЕ: я могу воспроизвести проблему с очень простым кодом:
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 ответа
Черт возьми, у меня наконец получилось. Я попробовал этот код из Google (было несколько источников.... Как мне приостановить рисование для элемента управления и его дочерних элементов ?... чтобы назвать один):
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();
}
Это не решило мою проблему и оставило меня с черными испорченными фонами... НО я подумал попробовать добавить следующее в метод Resume:
public static void Resume(this Control control)
{
control.Visible = false;
// existing code above....
control.Visible = true;
}
и БАМ!!! оно работает.
Хотя это и не является прямым ответом на вашу проблему, вы пытались добавить только один ElementHost (и, следовательно, только один WPF UserControl) к вашей WindowsForm.
Вы можете достичь этого, если создадите WPF UserControl, который объединяет все ваши индивидуальные WPF UserControl. Это жизнеспособное решение для вас? t может уменьшить или вы должны смешивать элементы управления Windows формы с WPF?