我如何(优雅地)在字符串的特定部分的标签上转置文本框? [英] How do I (elegantly) transpose textbox over label at specific part of string?

查看:28
本文介绍了我如何(优雅地)在字符串的特定部分的标签上转置文本框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将在Windows窗体上的标签中输入许多字符串(我不经常使用它们).字符串将类似于以下内容:

I'll be feeding a number of strings into labels on a Windows Form (I don't use these a lot). The strings will be similar to the following:

快速的棕色狐狸在l__y猎犬身上飞来飞去"

"The quick brown fox j___ed over the l__y hound"

我想在标签中显示字符串,但将TextBox确切地覆盖在缺少字母的位置.

I want to display the string in a label but overlay a TextBox exactly where the missing letters are.

将有300多个字符串,我正在寻找最简单,最优雅的方法.

There'll be 300+ strings, and I'm looking for the simplest, most elegant way to do it.

如何为每个字符串准确地重新定位文本框?

How do I reposition the textbox accurately for each string?

编辑:MaskTextBox无法使用,因为我需要多行支持.

A MaskTextBox won't work as I need multiline support.

推荐答案

为满足此要求,IMO最好使用Windows窗体的那些功能,这些功能允许与 HTML WPF 并托管一个 WebBrowser 控件或一个WPF ElementHost ,以向用户显示内容.在阅读此答案之前,请考虑:

To satisfy this requirement, IMO it's better to use those features of Windows Forms which allow interoperability with HTML or WPF and Host a WebBrowser control or a WPF ElementHost to show the content to users. Before reading this answer, please consider:

  • 用户不应清除 ____ 字段.如果他们可以清除它们,一旦移到另一个空白处,他们将失去查找已清除字段的能力.
  • 最好允许用户使用 Tab 键在 ____ 字段之间移动.
  • 在问题中提到: MaskTextBox无法使用,因为我需要多行支持.
  • 正如在问题中提到的:将有300多个字符串,因此混合使用许多Windows Forms控件不是一个好主意.
  • Users should not be able to clear the ____ fields. If they can clear them, once they moved to another blank, they will lose the ability to find the cleared field.
  • It's better to allow users to use Tab key to move between ____ fields.
  • As it's mentioned in the question: A MaskTextBox won't work as I need multiline support.
  • As it's mentioned in the question: There'll be 300+ strings so mixing a lot of Windows Forms control is not a good idea.

将HTML用作C#模型的视图并在WebBrowser控件中显示

在这里,我将基于在 WebBrowser 控件中显示HTML的基础上分享一个简单的答案.作为一种选择,您可以使用 WebBrowser 控件并创建合适的html,以使用模式类在 WebBrowser 控件中显示.

Here I will share a simple answer based on showing HTML in WebBrowser control. As an option you can use a WebBrowser control and create suitable html to show in WebBrowser control using a mode class.

主要思想是基于测验模型(包括原始文本和空白的空格)创建html输出,并使用html渲染模型并将其显示在 WebBrowser 控件中.

The main idea is creating an html output based on the quiz model (including the original text and ragnes of blanks) and rendering the model using html and showing it in a WebBrowser control.

例如,使用以下模型:

quiz = new Quiz();
quiz.Text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
quiz.Ranges.Add(new SelectionRange(6, 5));
quiz.Ranges.Add(new SelectionRange(30, 7));
quiz.Ranges.Add(new SelectionRange(61, 2));
quiz.Ranges.Add(new SelectionRange(82, 6));

它将呈现此输出:

然后在用户输入值之后,它将以这种方式显示:

Then after the user entered values, it will show this way:

最后,当您单击 Show Result (显示结果)按钮时,它将以绿色显示正确的答案,并以红色显示错误的答案:

And at last, when you click on Show Result button, it will show the correct answers in green color, and wrong answers in red color:

代码

您可以在此处下载完整的工作源代码,例如:

You can download full working source code for example here:

实现非常简单:

public class Quiz
{
    public Quiz() { Ranges = new List<SelectionRange>(); }
    public string Text { get; set; }
    public List<SelectionRange> Ranges { get; private set; }
    public string Render()
    {
        /* rendering logic*/
    }
}

这是 Quiz 类的完整代码:

public class Quiz
{
    public Quiz() { Ranges = new List<SelectionRange>(); }
    public string Text { get; set; }
    public List<SelectionRange> Ranges { get; private set; }
    public string Render()
    {
        var content = new StringBuilder(Text);
        for (int i = Ranges.Count - 1; i >= 0; i--)
        {
            content.Remove(Ranges[i].Start, Ranges[i].Length);
            var length = Ranges[i].Length;
            var replacement = $@"<input id=""q{i}"" 
                type=""text"" class=""editable""
                maxlength=""{length}"" 
                style=""width: {length*1.162}ch;"" />";
            content.Insert(Ranges[i].Start, replacement);
        }
        var result = string.Format(Properties.Resources.Template, content);
        return result;
    }
}

public class SelectionRange
{
    public SelectionRange(int start, int length)
    {
        Start = start;
        Length = length;
    }
    public int Start { get; set; }
    public int Length { get; set; }
}

这是html模板的内容:

And here is the content of the html template:

<html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=11" />
    <script>
        function setCorrect(id){{document.getElementById(id).className = 'editable correct';}}
        function setWrong(id){{document.getElementById(id).className = 'editable wrong';}}
    </script>
    <style>
        div {{
            line-height: 1.5;
            font-family: calibri;
        }}
        .editable {{
            border-width: 0px;
            border-bottom: 1px solid #cccccc;
            font-family: monospace;
            display: inline-block;
            outline: 0;
            color: #0000ff;
            font-size: 105%;
        }}
        .editable.correct
        {{    
            color: #00ff00;
            border-bottom: 1px solid #00ff00;
        }}
        .editable.wrong
        {{    
            color: #ff0000;
            border-bottom: 1px solid #ff0000;
        }}
        .editable::-ms-clear {{
            width: 0;
            height: 0;
        }}
    </style>
    </head>
    <body>
    <div>
    {0}
    </div>
    </body>
</html>

这篇关于我如何(优雅地)在字符串的特定部分的标签上转置文本框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆