3

我有一个 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);
    }
}
4

0 回答 0