C# GridView edycja danych. (DataBind nie odświeża wartości)

0

Witam
Mam następujący problem, dość dziwny.
Pisze stronę w ASP.NET z użyciem .Net Framework 3.5 SP1

Mam na niej UpdatePanel a na nim GridView z kilkoma kolumnami i wlaczonym guzikiem edycji. Jako DataSource podpiety wynik zapytania L2S.

Dokonuje Edycji danych w Event RowUpdating. Dane zostaja zmienione w bazie danych (jest to kilka kolumn). Update odbywa sie oczywiscie przy pomocy L2S.
W tym też evencie wykonuje ponownego przypisania DataSource i DataBind. Niestety mimo, że w bazie danych wartosci już są zmienione to nadal w gridzie pojawiaja się stare (nieodświeżone). Probowałem tez metody UpdatePanel(), nic nie pomoglo.

Najzabawniejsze, że mam druga stronę w której jest wszystko identycznie z tym, że do updatu jest brana tylko jedna kolumna i tam bez problemu następuje odświeżenie danych w Grid.

Proszę o jakieś sugestie co można jeszcze z tym zrobić?

<asp:ScriptManager ID="smGlowny" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="upUzytkownicy" runat="server">
        <ContentTemplate>
            
            <asp:GridView ID="gvListaUzytkownikow" runat="server" 
                AutoGenerateColumns="False" 
                onrowcancelingedit="gvListaUzytkownikow_RowCancelingEdit" 
                onrowediting="gvListaUzytkownikow_RowEditing" 
                onrowupdating="gvListaUzytkownikow_RowUpdating" 
                >
                    <Columns>
                        <asp:TemplateField HeaderText="Nazwa">
                            <EditItemTemplate>
                            
                            <asp:UpdateProgress ID="upIndicator" runat="server" DisplayAfter="0">
                                <ProgressTemplate>
                                  <asp:Image ID="Image1" runat="server" ImageUrl="~/Image/indicator.gif"/>  
                                </ProgressTemplate>
                            </asp:UpdateProgress>
                            
                                <asp:HiddenField ID="edIdUzytkownika" runat="server" Value='<%# Bind("ID_UZYTKOWNIKA") %>' />
                                <asp:TextBox ID="edLogin" runat="server" Text='<%# Bind("UZYTK_LOGIN") %>'></asp:TextBox>
                            </EditItemTemplate>
                            <ItemTemplate>
                                <asp:HiddenField ID="lbIdUzytkownika" runat="server" Value='<%# Bind("ID_UZYTKOWNIKA") %>' />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Wymuś zmianę hasła">
                            <EditItemTemplate>
                                <asp:CheckBox ID="edZmianaHasla" runat="server" 
                                    Checked='<%# Bind("WYMUS_ZMIANE_HASLA") %>'></asp:CheckBox>
                            </EditItemTemplate>
                            <ItemTemplate>
                                <asp:CheckBox ID="lbZmianaHasla" runat="server" 
                                    Checked='<%# Bind("WYMUS_ZMIANE_HASLA") %>' Enabled="false"></asp:CheckBox>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:CommandField HeaderText="Akcja" CancelText="Anuluj" EditText="Edytuj" ShowEditButton="True" 
                            UpdateText="Zapisz" />
                    </Columns>
                    </asp:GridView>
        </ContentTemplate>
    </asp:UpdatePanel>

CodeBehind:

protected void Page_Load(object sender, EventArgs e)
    {
        var Lista = Uzytk.ZwrocListe();
        gvListaUzytkownikow.DataSource = Lista;
        if (!IsPostBack)
        {
            gvListaUzytkownikow.DataBind();
        }

    }
protected void gvListaUzytkownikow_RowEditing(object sender, GridViewEditEventArgs e)
    {
        gvListaUzytkownikow.EditIndex = e.NewEditIndex;
        gvListaUzytkownikow.DataBind();
        
    }
 protected void gvListaUzytkownikow_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        var row = gvListaUzytkownikow.Rows[e.RowIndex];
        cUzytkownik UzytkUpdate = new cUzytkownik();
        UzytkUpdate.Id_Uzytkownika = System.Convert.ToInt32(((HiddenField)row.FindControl("edIdUzytkownika")).Value);
        UzytkUpdate.Login = ((TextBox)row.FindControl("edLogin")).Text;
        UzytkUpdate.WymusZmianeHasla = ((CheckBox)row.FindControl("edZmianaHasla")).Checked;
        upUzytkownicy.UpdateMode = UpdatePanelUpdateMode.Conditional;
        cUzytkownicy U = new cUzytkownicy();
        try
        {
            U.Update(UzytkUpdate); //Procedura do zmiany danych w bazie, przy pomocy L2S
        }
        finally
        {
            gvListaUzytkownikow.EditIndex = -1;
            var Lista = Uzytk.ZwrocListe(); //Metoda zwraca wynik zapytania L2S (select na tabeli)
            gvListaUzytkownikow.DataSource = Lista;
            gvListaUzytkownikow.DataBind();
            upUzytkownicy.Update();
        }
        
    }
 protected void gvListaUzytkownikow_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        gvListaUzytkownikow.EditIndex = -1;
        gvListaUzytkownikow.DataBind();
    }

0

Robisz to na piechotę.

Użyć obiektu ObjectDataSource, który zautomatyzuje ten proces (ty jedynie będzie musiał napisać odpowiednie metody dla Select, Update, Delete.

0

Jak już wspomnialem uzywam L2S (LINQ TO SQL), a do niego zalecane jest używanie LinqDataSource.

Stosuje się do wzorca projektowego MVC, chce odzielić warstwę logiki z warstwą prezentacji. Dlatego użycie tego obiektu raczej nie wchodzi w rachube (zależy mi na tym aby warstwa logiki była totalnie wymienna, z zachowaniem jedynie interafce)

Dziwi mnie, że to tak dziwacznie działa. Teoretycznie wszystko powinno smigac i smiga gdy edycji poddaje sie jedna kolumne.

Czy ktoś robił to właśnie w ten sposób ?

0

Powód jest taki, że zdarzenie Page_Load jest wywoływane zawsze jako pierwsze przed wszystkimi, które wykonujesz (Updating, Deleting) .. w ogóle przed wszystkimi innymi zdarzeniami.

To znaczy - Bind() wykonuje się jeszcze przed update'm.

Doraźnym rozwiązaniem jest wykonanie Bind() na końcu zdarzenia Updating..

Co do MCV .. - Chodziło mi bardziej o to, aby zawrzeć logikę warstwy pośredniej w ObjectDataSource. Samo użycie ObjectDataSource zapewni ci automatyczny Bind(*) kiedy trzeba, MVC na tym nie ucierpi (po prostu twój kod, który masz tu - zostanie przeniesiony do kodu klasy, której używa ObjectDataSource - kod ten będzie nawet bardziej uszczuplony).

GridView(frontend) --> ObjectDataSource --> LINQ provider --> DB

Frontend
Backend

0
Deti napisał(a)

Powód jest taki, że zdarzenie Page_Load jest wywoływane zawsze jako pierwsze przed wszystkimi, które wykonujesz (Updating, Deleting) .. w ogóle przed wszystkimi innymi zdarzeniami.

Nie do konca jest to prawda. Wczesniej wykonuje sie PageInit, ale nie o tym.
W kodzie, ktory wkleilem jest:

if (!IsPostBack)
        {
            gvListaUzytkownikow.DataBind();
        }

Co oznacza ze Bind wykona sie zawsze tylko nie wtedy gdy jest to callback, czyli np wywolanie przez zatwierdzenie formularza.

Deti napisał(a)

To znaczy - Bind() wykonuje się jeszcze przed update'm.

try
        {
            U.Update(UzytkUpdate); //Procedura do zmiany danych w bazie, przy pomocy L2S
        }
        finally
        {
            gvListaUzytkownikow.EditIndex = -1;
            var Lista = Uzytk.ZwrocListe(); //Metoda zwraca wynik zapytania L2S (select na tabeli)
            gvListaUzytkownikow.DataSource = Lista;
            gvListaUzytkownikow.DataBind();
            upUzytkownicy.Update();
        }

Przy callbacku jakim jest wykonanie tego kodu z przycisku, Bind wykonywany jest tylko w tym miejscu, po Update, sprawdzalem pulapkami w Visual Studio.

Deti napisał(a)

Co do MCV .. - Chodziło mi bardziej o to, aby zawrzeć logikę warstwy pośredniej w ObjectDataSource. Samo użycie ObjectDataSource zapewni ci automatyczny Bind(*) kiedy trzeba, MVC na tym nie ucierpi (po prostu twój kod, który masz tu - zostanie przeniesiony do kodu klasy, której używa ObjectDataSource - kod ten będzie nawet bardziej uszczuplony).

GridView(frontend) --> ObjectDataSource --> LINQ provider --> DB

Potęga MVC tkwi w tym, że warstwy są od siebie nie zależne. Dla warstwy prezentacji, warstwa logiki jest czarną skrzynką. Na tym właśnie polega ten schemat. Dzieki takiemu podejsciu, kiedy klientowi uwidzi się, że mam pobierać dane z pliku Excela a nie z bazy danych, lub co gorsza np z pliku txt (a takowe przypadki już miałem), nie będe musial robić totalnej rewolucji w kodzie, tylko podmienie kilka metod w klasie z warstwy logiki zachowując interface i klient dostaje to czego chce. Sam więc widzisz, że ograniczenie się do ObjectDataSource wcale w tym nie pomoże.

Wracając do problemu, wygląda to tak jakby wykonanie Submit przy zrobieniu Update bylo ze znacznym opoznieniem, dlatego databind lapie dane sprzed zatwierdzenia transakcji.
Czyżby zapytania LINQ były wykonywane asynchronicznie?
Jeśli tak czy jest jakiś sposób aby to obejść?

0

Fakt - nie zauważyłem bindowania w finally.

Wiem co to MVC .. ale jeszcze raz: ObjectDataSource przeniesie jedynie kod Update() do innej metody, a załatwi wiele rzeczy, które musisz robić na piechotę (w żadnym stopniu nie zmieni architektury MVC - będzie on po prostu kontrolerem)

Ale wracając do tematu - a spróbuj obsłużyć GridView.RowUpdated (w sensie: zbinduj tu)

0

W takim układzie (nie używam DataSourceId) RowUpdated nie zostanie nigdy wywołany.

If you're manually binding data to the GridView (not using a DataSourceID), then the RowUpdating event will fire after an update command, but the RowUpdated event will never fire.

http://forums.asp.net/t/1109769.aspx

1 użytkowników online, w tym zalogowanych: 0, gości: 1