2

簡単そうに見えますが、これがなかなか難しいです。

    <asp:TemplateField HeaderText="ID" InsertVisible="False" SortExpression="id">
        <ItemTemplate>
            <a href="/visit.aspx?Id=<%#Eval("Id")%>" id="ID" name="ID">  <%#Eval("Id")%> </a>
        </ItemTemplate>
    </asp:TemplateField>

グリッドビューの最後の列にボタンがあります。このボタンをクリックすると、データベースが更新され、グリッドビューが更新されます。また、gridview の id 列を見て、編集された行を強調表示しようとします。

ID フィールドが境界フィールドであり、URL でない場合、コードは問題なく機能します。しかし、それが URL の場合、URL のテキスト値を読み取ることができないようです。私はさまざまな解決策を試しました(SOとオンラインからの助け)

ハイパーリンク リンク = (ハイパーリンク)row.FindControl("id"); // 動作しませんでした

((HyperLink)GridView1.Rows[i].Cells[0].Controls[0]).Text // 機能しませんでした

これは、助けが必要なコード スニペットです。

            for (int i = 0; i < GridView1.Rows.Count; i++)
            {
                GridViewRow row;
                row = GridView1.Rows[i];
                if (row.RowType == DataControlRowType.DataRow)
                {

                    HyperLink link = (HyperLink)row.FindControl("id");
                    if (((HyperLink)GridView1.Rows[i].Cells[0].Controls[0]).Text == button.CommandName)
                    {
                        row.BackColor = System.Drawing.Color.IndianRed;
                     }
                }
            }

私は正常に動作するIDフィールドを保存するためにbutton.CommandNameを使用しています。テンプレートフィールド内のグリッドビューにハイパーリンクコントロールが見つからないようです。

私には意味をなさない次のエラーが表示されます

タイプ 'System.Web.UI.DataBoundLiteralControl' のオブジェクトをタイプ 'System.Web.UI.WebControls.HyperLink' にキャストできません。

Update1 ハイパーリンク フィールドを使用しない場合、このコードは問題なく動作します。

 for (int i = 0; i < GridView1.Rows.Count; i++)
                    {
                        GridViewRow row;
                        row = GridView1.Rows[i];
                        if (row.Cells[0].Text.Equals(button.CommandName))
                        {
                            row.BackColor = System.Drawing.Color.IndianRed;
                        }
                    }

列 0 をハイパーリンクに変更し、対応するコードを変更すると、機能しません。明らかに間違ったセルを読み取ることは問題ではありません。

for (int i = 0; i < GridView1.Rows.Count; i++)
{
    GridViewRow row;
    row = GridView1.Rows[i];
    HtmlAnchor anchor = (HtmlAnchor) row.Cells[0].Controls[0];
    if ( anchor.InnerText.Equals(button.CommandName))
    {
        row.BackColor = System.Drawing.Color.IndianRed;
 }
                }
4

1 に答える 1

2

まず最初FindControl("id");に、デザイン ビュー内のコントロールが実際にどこにあるかを確認しようとしています。大文字とID小文字が重要です。

もう1つのこと-これは、実際にはコントロールで<a>はなく、実際にはコントロールであるため、コントロールをキャストしようとしても何も起こらないためです。HyperLinkHtmlGenericControl

あなたは2つのことのいずれかを行うことができます-分離コードを変更して取得しますHtmlGenericControl link = (HtmlGenericControl )row.FindControl("ID");

または、デザイン ビューを変更して<asp:Hyperlink>、HTML の代わりにコントロールを使用します。<a>

あなたのエラーUnable to cast object of type 'System.Web.UI.DataBoundLiteralControl' (which is ain HTML terms) to type 'System.Web.UI.WebControls.HyperLink'.

((HyperLink)GridView1.Rows[i].Cells[0].Controls[0] 処理中の行の最初のセルの位置 0 にあるコントロールはリテラルであり、リンクではないと言っています。代わりに Controls[1] を見て、ごまかすことができます。

テーブルのレンダリングされた HTML を表示して、これを確認できます。リンクはスパン内またはスパンの隣にネストされます。

デバッグ中を調べControlsて、実際に何が含まれているかを確認します。

アップデート

コードを呼び出す方法については、多くの混乱があります。あなたがe.Row.RowTypeこれをやっていると私に信じさせるRowDataBound.

この場合、このメソッドはすべての行で呼び出されるため、すべてのグリッドビュー行をループする必要はありません。したがって、各行を呼び出し、次にグリッド内の各行を呼び出すことになります。大きなグリッド。

代わりにこれを試してください。その 1 つの行にのみ関心があります。

また、どこbutton.CommandNameから入手したのかわからない

このためには、FindControl メソッドを調べて、実際にハイパーリンク コントロールであることを確認する必要があります。

if ((e.Row.RowType == DataControlRowType.DataRow)) {
    GridViewRow row = e.Row;
    // get your link - if indeed the control IS a hyperlink
        // this will be null if the control "id" is NOT a hyperlink control
    HyperLink link = (HyperLink)row.FindControl("id");
    if ((link.Text == Button.CommandName)) {
        row.BackColor = Drawing.Color.IndianRed;
    }
}

最後の更新...

わかりました-さらにコメントした後、コントロールを再帰的に検索する必要があると思います。これは、FindControlコントロール内の直接コントロールのみを参照するためです。コントロール内のコントロール内のコントロールは見つかりません - IE FindControl は最初の子のみを調べ、孫は調べません。

したがって、好きな場所にこのメソッドを作成します。

public static Control FindControlRecursive(Control Root, string Id)
{
    if (Root.ID == Id) { return Root; }

    foreach (Control Ctl in Root.Controls)
    {
        Control FoundCtl = FindControlRecursive(Ctl, Id);
        if (FoundCtl != null) { return FoundCtl; }
    }
    return null;
}

次に、行と探しているコントロールの ID を渡します。

このように-変更:

 HyperLink link = (HyperLink)row.FindControl("id");

これに - 私はあなたの小文字を保持していることに注意してくださいid- あなたが小文字を使用しているか大文字を使用しているかどうかわからない - この方法はあなたのために小さなバグを追い出します:)

Control link = FindControlRecursive(row, "id");

コントロールを取得したら、必要なものにキャストできます/またはあるべきものにキャストできます

于 2013-08-09T17:37:53.923 に答える