2

クライアント側で生成された HTML 行 ( <tr>) があります。コントロールの行セル情報を含む文字列を変換したいと考えていますHtmlTableRow。これは、Convert string to WebControls - asp.netの例を使用してこれまで行ってきたことです。ありがとう

    string row = "<tr><td>item</td><td><input name=\"radio0\" type=\"radio\"/></td></tr>";
    Dictionary<string, HtmlContainerControl> controlConstructor = new Dictionary<string, HtmlContainerControl>
                                                {

                                                    {"tr", new HtmlTableRow()},
                                                    {"td", new HtmlTableCell()}
                                                };
    var htmlDoc = XElement.Parse(row);
    Func<XElement, HtmlControl> constructHtmlStructure = null;
    constructHtmlStructure = (o =>
                                {
                                    var control = controlConstructor[o.Name.ToString()];
                                    if (o.HasElements)
                                    {
                                        control.Controls.Add(constructHtmlStructure(o.Elements().Single())); //Exception: Sequence contains more than one element (When is a input item)
                                    }
                                    else
                                    {
                                        control.InnerText = o.Value;
                                    }
                                    return control;
                                });

    HtmlTableRow structure = (HtmlTableRow)constructHtmlStructure(htmlDoc);
4

2 に答える 2

1

文字列を HtmlTableRow に解析するもっと簡単な方法を使用しないのはなぜですか。

あなたDictionary<string, HtmlContainerControl> controlConstructor は と のみtrを考慮しますtd、それらの中にネストされた入力コントロールはどうですか?

sequence contains more than one elementそのため、 foreach ループを使用してその " " を回避したとしても、" " エラーが発生します"key doesn't exist

それを克服したとしても(辞書に入力キーを追加することで)、それを に解析することはできませんHtmlContainerControl

たとえそうしても、に更新するDictionary<string, HtmlContainerControl>ことによってDictionary<string, HtmlControl>、その入力コントロールを処理する方法を考える必要があります。control.InnerText = o.value;

したがって、はるかに簡単な方法:

string row = "<tr><td>item</td><td><input name=\"radio0\" type=\"radio\"/></td></tr>";
        XmlDocument doc = new XmlDocument();
        doc.LoadXml(row);

        HtmlTableRow tblRow = new HtmlTableRow();
        foreach (XmlNode node in doc.SelectSingleNode("tr").ChildNodes)
        {
            HtmlTableCell cell = new HtmlTableCell();
            cell.InnerText = node.InnerXml;
            foreach (XmlNode childNode in node.ChildNodes)
            {
                if (childNode.Name == "input")
                {
                    if (childNode.Attributes["type"] != null)
                    {
                        switch (childNode.Attributes["type"].Value.ToString())
                        {
                            case "radio":
                                HtmlInputRadioButton rad = new HtmlInputRadioButton();
                                rad.Name = childNode.Attributes["name"].ToString();
                                cell.Controls.Add(rad);

                                break;

                            ///other types of input controls
                            default:
                                break;
                        }

                    }
                    else
                    {
                        HtmlInputButton button = new HtmlInputButton("button");
                        cell.Controls.Add(button);
                    }
                }
            }
            tblRow.Cells.Add(cell);
        }

ご覧のとおり、これは非常に大雑把で厳密なロジックです。最善の方法は、再帰関数を考え出し、HtmlTableRow を構築することです。

于 2013-03-02T21:23:42.800 に答える
0

Linq のSingleメソッドは、シーケンスの最初で唯一の要素を返します。要素が複数ある場合は、表示されている例外をスローします。テーブルの行には 2 つのテーブル セルが含まれているため、そのo.Elements()メソッドは 2 つのメンバーを含む列挙型を返し、使用Singleすると失敗します。

使用する代わりに:

control.Controls.Add(constructHtmlStructure(o.Elements().Single()));

...使用する:

foreach(var element in o.Elements())
{
    control.Controls.Add(constructHtmlStructure(element));
}

このようにして、表の各行のセルを繰り返し処理し、それぞれをコントロールに追加します。

編集

もう 1 つ変更する必要があります。ディクショナリには が 1 つだけ含まれHtmlTableRowHtmlTableRowおり、どちらも にアクセスするまでにすでに作成されていますconstructHtmlStructure。既存のオブジェクト (したがって、利用可能な各オブジェクトのインスタンスは 1 つだけ) を用意する代わりに、必要に応じてディクショナリで各タイプの新しいインスタンスを作成する必要があります。

したがって、これの代わりに(間隔を調整して):

var controlConstructor = new Dictionary<string, HtmlContainerControl>
{
    { "tr", new HtmlTableRow() },
    { "td", new HtmlTableCell() }
};

...

var control = controlConstructor[o.Name.ToString()];

...これを試して:

var controlConstructor = new Dictionary<string, Func<XElement, HtmlControl>>
{
    { "tr", o => new HtmlTableRow() },
    { "td", o => new HtmlTableCell() }
};

...

var control = controlConstructor[o.Name.ToString()].Invoke(o);

XElement次のようなから入力を作成する関数も必要です。

private static HtmlControl CreateInputFromElement(XElement element)
{
    // Create an appropriate HtmlInputControl...
}

...次のように辞書に追加できます。

var controlConstructor = new Dictionary<string, Func<XElement, HtmlControl>>
{
    { "tr", o => new HtmlTableRow() },
    { "td", o => new HtmlTableCell() },
    { "input", CreateInputFromElement }
};
于 2013-03-02T21:13:51.333 に答える