简体   繁体   English

C#,可访问性和只读

[英]C#, accessibility and readonly

I am working on a relatively complex job management program in C#. 我正在C#中开展一个相对复杂的工作管理计划。

All the data entry forms inherit from a parent that uses the same custom navigation bar (rather similar to the BindingNavigator). 所有数据输入表单都继承自使用相同自定义导航栏的父级(类似于BindingNavigator)。 By default, none of the data entry controls are enabled when navigating through records. 默认情况下,在浏览记录时不会启用任何数据输入控件。 The user has to explicitly enable editing before a record can be edited. 在编辑记录之前,用户必须明确启用编辑。 This works just fine. 这很好用。 However, the reason for me to migrate this entire project was to make the application accessible for screen readers before I finally lose my sight completely. 但是,我迁移整个项目的原因是为了让屏幕阅读器可以访问应用程序,然后我终于彻底失去了视力。

My problem is that the controls containing the data in the records become completely invisible to the screen reader if they are not enabled. 我的问题是如果未启用包含记录中数据的控件对屏幕阅读器完全不可见。 The obvious answer is to make them read-only rather than disabling them, which is fine for text boxes, masked text boxes, NumericUpDown controls, but is not available for checkboxes, radio buttons or combo boxes. 显而易见的答案是将它们设置为只读而不是禁用它们,这对于文本框,屏蔽文本框,NumericUpDown控件来说很好,但不适用于复选框,单选按钮或组合框。

Is there any way to prevent these from being changed while still allowing a screen reader to access them? 有没有办法防止这些被更改,同时仍允许屏幕阅读器访问它们? Or does anyone have a coherent solution for all the controls listed above? 或者是否有人对上面列出的所有控件都有一致的解决方案?

Thanks in advance. 提前致谢。

The way that we have handled this in the past in WinForms is to make custom versions of each of the controls and implement readonly on our own. 我们过去在WinForms中处理这个问题的方法是为每个控件制作自定义版本并自行实现readonly。

The basic approach is to intercept the appropriate "changed" event for the control and revert the user's action that they just took when the control has indicated it is to be readonly. 基本方法是拦截控件的相应“已更改”事件,并在控件指示它只是只读时恢复用户刚刚执行的操作。

For checkbox, here is a very rough implementation: 对于复选框,这是一个非常粗略的实现:

public class MyCheckBox : CheckBox
{
    public bool ReadOnly {get; set;}
    private bool m_fInEvent;
    protected override void  OnCheckedChanged(EventArgs e)
    {
        if (ReadOnly) {
            if (!m_fInEvent) {
                try {
                    // Prevent infinite recursion
                    m_fInEvent = true;
                    this.Checked = !this.Checked;
                } finally {
                    m_fInEvent = false;
                } 
            }
        }
        base.OnCheckedChanged(e);
    }
}

Assuming you are using winform, maybe you can use Autocheck for the checkbox. 假设您使用的是winform,也许您可​​以使用Autocheck来获取复选框。

and for combobox you can try this: 对于组合框你可以试试这个:

stateComboBox.DropDownStyle = ComboBoxStyle.DropDownList;

I Later realized that the radio buttons in the application were not affected by the problem. 我后来意识到应用程序中的单选按钮不受问题的影响。

Ultimately, after a lot of difficulty with the ComboBox, I came up with these two classes: 最后,在使用ComboBox遇到很多困难之后,我想出了这两个类:

public class ReadOnlyCheckBox : CheckBox
{
    public bool ReadOnly { get; set; }
    protected override void OnKeyUp(KeyEventArgs e)
    {
        if (!ReadOnly)
        {
            base.OnKeyUp(e);
        }
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (!ReadOnly)
        {
            base.OnKeyDown(e);
        }
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        if (!ReadOnly)
        {
            base.OnMouseUp(e);
        }
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (!ReadOnly)
        {
            base.OnMouseDown(e);
        }
    }
}
public class ReadOnlyComboBox : ComboBox
{
    public bool ReadOnly { get; set; }
    protected override void OnKeyUp(KeyEventArgs e)
    {
        if (ReadOnly)
        {
            e.Handled = true;
        }
        else
            base.OnKeyUp(e);

    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        if (ReadOnly)
        {
            e.Handled = true;
        }
        else
            base.OnKeyDown(e);
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (!ReadOnly)
            base.OnMouseDown(e);
        else
        {
            Enabled = false;
            Enabled = true;
            this.Focus();
        }
    }
}

No matter what I tried, the Combo always seemed to handle key and mouse events, even if I didn't call the base methods. 无论我尝试什么,Combo似乎总是处理键和鼠标事件,即使我没有调用基本方法。 hence the different approaches in the two classes. 因此这两个类别的方法不同。

Both the KeyDown and KeyUp events have to be trapped in the checkbox because by default the KeyDown event grays out the checkbox and the keyup event actually checks the box and restores the normal background. KeyDown和KeyUp事件都必须被困在复选框中,因为默认情况下KeyDown事件会使复选框灰显,keyup事件实际上会检查框并恢复正常背景。

As far as I can see, it's robust and never allows the state of the controls to change, which could possibly have fired other unwanted actions. 据我所知,它很强大,永远不会允许控件的状态发生变化,这可能会引发其他不需要的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM