如果其他控件上的验证失败,则允许按钮单击事件

时间:2014-08-03 18:44:13

标签: c# .net winforms

我有一个有趣的问题,我不知道如何解决。我写了一个更改密码的表单。表单在只读TextBox中也显示当前密码(不用于验证目的;在这种情况下这并不重要。)每个密码TextBox中都有一个按钮,当单击时,屏蔽或取消屏蔽密码(替换密码)带子弹的角色,反之亦然。)这是整个事物的图像:

screenshot

注意遮罩/取消遮罩按钮是如何放在文本框内的,而不是在它们之外。按钮已放置在文本框内:

var button = new Button();
button.Width = 20;
button.Cursor = Cursors.Default;
button.FlatStyle = FlatStyle.Flat;
button.Image = SystemIcons.Shield.ToBitmap();
button.Dock = DockStyle.Right;
button.CausesValidation = false;
textBox.Controls.Add(button);

最后一个TextBox启用了验证。现在的问题是,用户无法单击另一个文本框上的passwork unmask按钮,因为验证事件失败。因此,用户无法在不输入新密码的情况下查看当前密码。

即使验证在文本框中失败,我也需要一种可以点击密码掩码/取消掩码按钮的方法。我什么都想不到。在文本框外移动这些按钮不是一种选择。

取消屏蔽按钮本身以及文本框的父级都将CausesValidation设置为false。只有文本框本身将其设置为true

这是Visual Studio 2010中的.NET 2.0 C#项目。

2 个答案:

答案 0 :(得分:1)

使用文本框的Validating事件做起来并不容易。当文本框失去焦点时,单击事件甚至不会到达按钮。我认为您可以创建自己的TextBox(通过扩展TextBox或TextBoxBase)并破解那里的验证行为或覆盖表单DefWndProc并捕获鼠标事件+相关信息(坐标)当验证失败时,仍然会发送它们(可能会变得难看)。

一个简单的方法是不再依赖Validating事件。而是在文本框的Leave事件中进行验证,如果失败则只标记文本框。用户仍然会发现存在问题。

您需要注意的另一件事是对话框的OK按钮。如果表单上存在未经验证的控件,则需要确保用户无法关闭对话框。由于您不再拥有验证支持,因此当数据无效时,您可以使用Tag属性存储False(例如)。在OK上,只需遍历所有文本框并检查其标记。

最终用户的行为最终将是相同的,您只需要编写更多代码。

答案 1 :(得分:1)

好吧,我找到了一种方法,可以继续使用Validating事件,并且仍然可以单击其他文本框中的按钮。事实证明,即使按钮没有焦点,也会发送Button.MouseUp事件。

因此解决方案是同时处理MouseUp和Click事件并执行密码屏蔽/取消屏蔽,具体取决于包含按钮的文本框当前是否具有键盘焦点:

button.MouseUp += (sender, e) =>
{
    if (button.Parent.ContainsFocus || e.Button != MouseButtons.Left
        || !button.ClientRectangle.Contains(e.Location))
    {
        return;
    }
    textBox.UseSystemPasswordChar = !textBox.UseSystemPasswordChar;
};

button.Click += delegate
{
    if (!button.Parent.ContainsFocus) {
        return;
    }
    textBox.UseSystemPasswordChar = !textBox.UseSystemPasswordChar;
};

我们确实希望处理这两个事件,因为如果我们只处理MouseUp,然后用键盘点击按钮(Tab键切换到按钮,Enter键或空格点击它)将不再有效。