GridView należy umieścić wewnątrz tagu formularza z runat = „server”, nawet jeśli GridView znajduje się w tagu formularza


86
<form runat="server" id="f1">
    <div runat="server" id="d">
        grid view:
        <asp:GridView runat="server" ID="g">
        </asp:GridView>
    </div>

    <asp:TextBox runat="server" ID="t" TextMode="MultiLine" Rows="20" Columns="50"></asp:TextBox>
</form>

Kod za:

public partial class ScriptTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        g.DataSource = new string[] { "a", "b", "c" };
        g.DataBind();

        TextWriter tw = new StringWriter();
        HtmlTextWriter h = new HtmlTextWriter(tw);    
        d.RenderControl(h);
        t.Text = tw.ToString();
    }
}

Nawet widok GridView znajduje się w tagu from z runat = "server", nadal otrzymuję ten błąd.

Jakieś wskazówki?


2
Widziałem to już wcześniej, jeśli ktoś używa strony wzorcowej, która ma już tag formularza (który może, ale nie musi, być już deklarowany runat="server"w swoim <form>tagu). Tylko myśl ...
lhan

@Lloyd: Ale nie mam żadnej strony wzorcowej, stworzyłem tę stronę tylko do testowania tego błędu.
teenup

Cześć, skopiowałem Twój kod, ale nie mogę odtworzyć problemu. Czy możesz umieścić całą zawartość pliku (każdą linię) w swoim pytaniu lub wkleić go? Dzięki
christofr

Odpowiedzi:


174

Wołasz GridView.RenderControl(htmlTextWriter), stąd strona zgłasza wyjątek, że kontrolka serwera została wyrenderowana poza formularzem.

Można uniknąć tego wykonania, zastępując VerifyRenderingInServerForm

public override void VerifyRenderingInServerForm(Control control)
{
  /* Confirms that an HtmlForm control is rendered for the specified ASP.NET
     server control at run time. */
}

Zobacz tutaj i tutaj .


Mam widok GridView, którego zawartość chcę wyrenderować na wiadomość e-mail, dlatego muszę wyrenderować go poza formularzem. Nie mogę zastąpić tej metody, ponieważ strona hosta to Sharepoint. My Grid to kontrolka użytkownika wewnątrz składnika Web Part na stronie programu SharePoint.
teenup

Ponadto, gdy dynamicznie dodam ten widok GridView bezpośrednio do HtmlForm, a następnie wyrenderuję go, renderuje się doskonale. Oznacza to, że wymaga jedynie obecności formy poza siatką. Ale kiedy dynamicznie dodam ten DIV do HtmlForm, ten błąd pojawia się ponownie, chociaż Grid jest dzieckiem DIV i również został dodany do HtmlForm razem z nim.
teenup

to nie zadziała, jeśli twoja siatka znajduje się w kontrolce użytkownika .ascx. w takim przypadku zobacz odpowiedź Chrisa Mullinsa poniżej. Użyłem zarówno technik Tima, jak i Chrisa i działają świetnie.
Taylor Brown

Uwielbiam eleganckie rozwiązanie! Podnieca mnie: D
Nikolay

3
Działało świetnie. Wystarczy ostrzeżenie, że może pojawić się komunikat o błędzie: „RegisterForEventValidation można wywołać tylko podczas Render ();” Jeśli tak, pamiętaj, aby ustawić EventValidation na false w znacznikach strony.
Al Belmondo,

29

Alternatywą dla zastąpienia VerifyRenderingInServerForm jest usunięcie siatki z kolekcji kontrolek podczas renderowania, a następnie dodanie jej z powrotem po zakończeniu przed załadowaniem strony. Jest to przydatne, jeśli chcesz mieć jakąś ogólną metodę pomocniczą do pobierania gridu html, ponieważ nie musisz pamiętać o dodaniu nadpisania.

Control parent = grid.Parent;
int GridIndex = 0;
if (parent != null)
{
    GridIndex = parent.Controls.IndexOf(grid);
    parent.Controls.Remove(grid);
}

grid.RenderControl(hw);

if (parent != null)
{
    parent.Controls.AddAt(GridIndex, grid);
}

Inną alternatywą, aby uniknąć zastąpienia, jest zrobienie tego:

grid.RenderBeginTag(hw);
grid.HeaderRow.RenderControl(hw);
foreach (GridViewRow row in grid.Rows)
{
    row.RenderControl(hw);
}
grid.FooterRow.RenderControl(hw);
grid.RenderEndTag(hw);

Zręczny!! Jutro spróbuję.
teenup

podczas próby renderowania siatki wewnątrz kontrolki użytkownika asp (.ascx), użycie pierwszej metody działało świetnie.
Taylor Brown

3
Nie działa, jeśli gridview zawiera kontrolki takie jak LinkButton - daje 'Control typu' LinkButton 'musi być umieszczona wewnątrz tagu formularza z błędem runat = server'. 2. Czy mógłbyś wyjaśnić, dlaczego ta technika działa?
BornToCode

@BornToCode Wyłącz sortowanie dla widoku siatki w kodzie.
Adi Solar

14

Zaraz po załadowaniu strony dodaj to:

public override void VerifyRenderingInServerForm(Control control)
{
    //base.VerifyRenderingInServerForm(control);
}

Zwróć uwagę, że nic nie robię w funkcji.

EDYCJA: Tim odpowiedział to samo. :) Odpowiedź znajdziesz również tutaj


2

Chcę tylko dodać inny sposób zrobienia tego. Widziałem, jak wiele osób w różnych powiązanych wątkach pytało, czy możesz użyć VerifyRenderingInServerForm bez dodawania go do strony nadrzędnej.

Właściwie możesz to zrobić, ale jest to trochę brzydkie.

Najpierw utwórz nową klasę Page, która wygląda mniej więcej tak:

public partial class NoRenderPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    { }

    public override void VerifyRenderingInServerForm(Control control)
    {
        //Allows for printing
    }

    public override bool EnableEventValidation
    {
        get { return false; }
        set { /*Do nothing*/ }
    }
}

Nie musi mieć skojarzonego z nim pliku .ASPX.

Następnie w kontrolce, którą chcesz wyrenderować, możesz wykonać następujące czynności.

    StringWriter tw = new StringWriter();
    HtmlTextWriter hw = new HtmlTextWriter(tw);

    var page = new NoRenderPage();
    page.DesignerInitialize();
    var form = new HtmlForm();
    page.Controls.Add(form);
    form.Controls.Add(pnl);
    controlToRender.RenderControl(hw);

Teraz masz oryginalną kontrolkę renderowaną jako HTML. Jeśli potrzebujesz, dodaj kontrolkę z powrotem do jej pierwotnej pozycji. Masz teraz wyrenderowany HTML, stronę normalną i bez zmian w samej stronie.


@DanielEdwards, co robi dla Ciebie DesignerInitialize ()?
JJS,

To działa, ale musiałem użyć go HttpContext.Current.Server.Execute(page, writer, false);do napisania HTML - wywołanie controlToRender.RenderControl(hw);nie powodowało żadnego zdarzenia kontrolnego, np. Page_LoadWięc podczas renderowania kontrolki było puste.
DGibbs

0

Oto mój kod

protected void btnExcel_Click(object sender, ImageClickEventArgs e)
    {
        if (gvDetail.Rows.Count > 0)
        {
            System.IO.StringWriter stringWrite1 = new System.IO.StringWriter();
            System.Web.UI.HtmlTextWriter htmlWrite1 = new HtmlTextWriter(stringWrite1);
            gvDetail.RenderControl(htmlWrite1);

            gvDetail.AllowPaging = false;
            Search();
            sh.ExportToExcel(gvDetail, "Report");
        }
    }

    public override void VerifyRenderingInServerForm(Control control)
    {
        /* Confirms that an HtmlForm control is rendered for the specified ASP.NET
           server control at run time. */
    }

Dlaczego dodałeś tę odpowiedź 5 lat po udzieleniu odpowiedzi? To ta sama odpowiedź.
Mukus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.