开发者

How can I dynamically replace portions of text with TextBoxes?

开发者 https://www.devze.com 2023-03-06 03:12 出处:网络
TL;DR: I need to insert a TextBox into a PlaceHolder wherever I see a token like @token@, and splitting on @ won\'t cut it. How can I do this?

TL;DR:

I need to insert a TextBox into a PlaceHolder wherever I see a token like @token@, and splitting on @ won't cut it. How can I do this?

Setup:

I have a data开发者_如何学编程base-driven ASP.NET page with merge fields in several places. On one of the admin pages, I want to make the text in the merge fields editable by showing TextBoxes where the merge fields are. The rest of the text needs to stay non-editable.

The input looks like this:

"the quick brown fox @foo@ jumps over @bar@ the lazy @baz@ dog."

The merge fields here would be foo, bar, and baz. I have a Dictionary<string, string> with the value of the merge fields:

var Tokens = new Dictionary<string, string>
{
    { "foo", "john" },
    { "bar", "george" },
    //...etc...
};

Goal:

For each of these text blocks, I have a PlaceHolder. What I'd like to do is dynamically insert a Label for each block of uneditable text, and a TextBox for each editable block. So the results of the above would be as if I had hard-coded something like this:

<asp:Label   Text="the quick brown fox" />
<asp:TextBox ID="foo" Text="john" />
<asp:Label   Text="jumps over" />
<asp:TextBox ID="bar" Text="george" />
<asp:Label   Text="the lazy" />
...etc...

Problem:

Matching the @token@ pattern is easy. The trick is adding the Labels and TextBoxes in the right places. There might be more than one token in a given input, so I have to separate it out into editable and non-editable text, while still keeping track of which merge variable each TextBox corresponds to. As it turns out, this is not as easy as it sounds. I could use regular expressions to convert the input string into HTML, replacing the @token@ pattern with <input> tags. However, that has a couple of problems:

  • I already have a ton of code for the dynamic-server-controls approach.
  • I only want to match specific tokens, so /@[a-zA-Z\d]+@/ isn't strict enough.

Previous Strategy:

Until now, I simply split the input string on @, then inserted a Label for each odd-numbered substring and a TextBox for each even substring. That worked fine, but the requirements are changing. @ symbols will now be allowed outside of a variable name, so the input string might look like:

blah blah@blah.com @foo@ blah

...in which case only foo would be a merge field.

Current Strategy:

I feel like I need to iterate through Tokens and build some sort of array of Labels and TextBoxes. The problem is that any number of tokens might be in the input, so once I split out TextBoxes for @foo@, I need to go through the text again for instances of @bar@. I think I need some sort of recursion for this, but I can't quite put my finger on it.


you can do it with Regular expressions. The Expression would look something like:

@([a-zA-Z0-9])+@

this would mean that it matches for all patterns which start with @, contain at least one character a-z or A-Z or 0-9 and end with @

Regex.Match


Before fantasticfix's answer was posted, I started working on a recursive method using string manipulation. It seems to be working correctly, so I'm posting it here for anyone else:

private void tokenize(PlaceHolder ph, string str)
{
    int index = str.IndexOf('@') + 1;

    if (index == 0)
    {
        ph.Controls.Add(new Label { Text = str });
        return;
    }

    ph.Controls.Add(new Label { Text = str.Substring(0, index - 1) });

    if (Tokens.Keys.Any(k => str.Substring(index).StartsWith(k + "@")))
    {
        int next = str.IndexOf("@", index);
        string key = str.Substring(index, next - index);

        ph.Controls.Add(new TextBox
        {
            ID = "txt" + key,
            Text = Tokens[key],
            TextMode = TextBoxMode.MultiLine,
            Rows = 2
        });

        index = next + 1;
    }

    tokenize(ph, str.Substring(index));
}
0

精彩评论

暂无评论...
验证码 换一张
取 消