我有一个 Winform 应用程序,其中混合了 Winform 和 ElementHost 上托管的 WPF 控件。当 winform 文本框因单击 WPF 控件而进入验证状态时,并且存在验证错误,ElementHost 不断触发 Focus 事件,这使我的应用程序卡住了。
如果有办法解决,请指教。
我创建了一个示例应用程序来复制该问题。
我有一个 Form1,其中包含 2 个 winform 文本框(textbox1、textbox2)和一个托管在 ElementHost 上的 WPF 控件。
textbox1_validating 事件处理程序检查输入是否不是“1”,然后通过将事件参数 e.Cancel 设置为 true 来取消事件。如果 textbox1 因为单击了其他 winform 控件而进入验证状态,则此方法效果很好。
但是,如果 textbox1 由于 WPF 控件获得焦点而进入验证状态,则取消事件不起作用。ElementHost 不断触发 Focus 事件,导致 textbox1_validating 被一次又一次地调用。
用户控制代码:
<UserControl x:Class="WpfControlLibrary1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="54" d:DesignWidth="295" >
<Grid Height="43">
<TextBox Height="20" HorizontalAlignment="Left" Name="textBox1" VerticalAlignment="Top" Width="106" Text="Default1" />
<TextBox Height="20" HorizontalAlignment="Left" Margin="130,0,0,0" Name="textBox2" VerticalAlignment="Top" Width="73" Text="Default2" />
</Grid>
WinForm 代码:
public partial class Form1 : Form
{
public static bool HasError = false;
public Form1()
{
InitializeComponent();
}
private void textBox1_Validating(object sender, CancelEventArgs e)
{
if (textBox1.Text != "1" && textBox1.Text != "")
{
MessageBox.Show("Input is invalid, expecting \"1\". ");
HasError = true;
e.Cancel = true;
}
}
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.textBox2 = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this._durationCtrlHost = new WindowsFormsApplication1.DurationCtrlHost();
this._durationCtrl = new WpfControlLibrary1.UserControl1();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(120, 23);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(242, 20);
this.textBox1.TabIndex = 0;
this.textBox1.Enter += new System.EventHandler(this.textBox1_Enter);
this.textBox1.Validating += new System.ComponentModel.CancelEventHandler(this.textBox1_Validating);
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(121, 56);
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(240, 20);
this.textBox2.TabIndex = 2;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(24, 30);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(90, 13);
this.label1.TabIndex = 4;
this.label1.Text = "WinformTextbox1";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(25, 63);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(90, 13);
this.label2.TabIndex = 5;
this.label2.Text = "WinformTextbox2";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(24, 104);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(64, 13);
this.label3.TabIndex = 6;
this.label3.Text = "WPFControl";
//
// _durationCtrlHost
//
this._durationCtrlHost.Location = new System.Drawing.Point(120, 90);
this._durationCtrlHost.Name = "_durationCtrlHost";
this._durationCtrlHost.Size = new System.Drawing.Size(271, 60);
this._durationCtrlHost.TabIndex = 3;
this._durationCtrlHost.Child = this._durationCtrl;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(420, 282);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.textBox2);
this.Controls.Add(this.textBox1);
this.Controls.Add(this._durationCtrlHost);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
}
public class DurationCtrlHost : ElementHost
{
private const int WM_SETFOCUS = 0x0007;
private const int WM_KILLFOCUS = 0x0008;
private int SetFocusFiredCount = 0;
private int KillFocusFiredCount = 0;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SETFOCUS)
{
SetFocusFiredCount++;
if (Form1.HasError)
return;
}
else if (m.Msg == WM_KILLFOCUS)
{
KillFocusFiredCount++;
}
base.WndProc(ref m);
}
}