[asp.net] Eventhandlers aan alle gridviews koppelen

Pagina: 1
Acties:

  • sopsop
  • Registratie: Januari 2002
  • Laatst online: 08:43

sopsop

[v] [;,,;] [v]

Topicstarter
Een klant van mij wil per se binnen een gridview op een pagina zowel de numerieke aanduiding als een vorige-volgende knop hebben. Da's prima, maar dat kan de gridview control niet.
Daarom heb ik een eventhandler op het RowCreated event gemaakt, die -indien de pagersettings numeriek zijn- een vorige en volgende knop aanmaakt, die weer een subje aanroepen om de volgende pagina te selecteren. Het werkt als een tierelier.

De code:
De RowCreated eventhandler
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    Protected Sub AddPrevNextToGrid(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
        If e.Row.RowType = DataControlRowType.Pager Then
            Dim pagerTable As Table = DirectCast(e.Row.Cells(0).Controls(0), Table)
            Dim grd As GridView = DirectCast(sender, GridView)
            Dim pagerRow As TableRow = pagerTable.Rows(0)
            Dim pagerSettings As PagerSettings = grd.PagerSettings
            Dim cellsCount As Integer = pagerRow.Cells.Count

            If pagerSettings.Mode = PagerButtons.Numeric OrElse pagerSettings.Mode = PagerButtons.NumericFirstLast Then
                'check whether previous button exists 
                Dim btnPrev As New LinkButton
                btnPrev.Text = pagerSettings.PreviousPageText
                btnPrev.CommandName = "Prev"
                If grd.PageIndex <= 0 Then btnPrev.Visible = False
                AddHandler btnPrev.Command, AddressOf PrevNextClick
                Dim PrevCell As New TableCell

                PrevCell.Controls.Add(btnPrev)
                pagerRow.Cells.AddAt(0, PrevCell)

                'check whether previous button exists 
                Dim btnNext As New LinkButton
                btnNext.Text = pagerSettings.NextPageText
                btnNext.CommandName = "Next"
                If grd.PageIndex >= grd.PageCount - 1 Then btnNext.Visible = False
                AddHandler btnNext.Command, AddressOf PrevNextClick
                Dim NextCell As New TableCell
                NextCell.Controls.Add(btnNext)
                pagerRow.Cells.Add(NextCell)
            End If
        End If
    End Sub


De Vorige/Volgende knop eventhandler
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
    Protected Sub PrevNextClick(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.CommandEventArgs)
        Dim lnkBut As LinkButton = sender
        Dim grd As GridView = lnkBut.Parent.Parent.Parent.Parent.Parent.Parent.Parent
        Select Case e.CommandName.ToUpper
            Case "PREV"
                grd.PageIndex +=  -1
            Case "NEXT"
                grd.PageIndex +=  1
        End Select
    End Sub


Het koppelen van een gridview aan de rowcreated eventhandler
Visual Basic .NET:
1
2
3
    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        AddHandler GridLopendeZakenMap.RowCreated, AddressOf AddPrevNextToGrid
    End Sub


Nu heb ik hierover twee vragen:
Kan ik op een snellere manier bij de parent gridview van de linkbutton komen? Dit aangezien ik de methode die ik nu toepas behoorlijk lelijk en gevoelig voor fouten vind:
Visual Basic .NET:
1
lnkBut.Parent.Parent.Parent.Parent.Parent.Parent.Parent


Ik heb ook al geprobeerd om de naam van de gridview als commandargument mee te geven, maar dan kan ik de gridview niet vinden met findcontrol.

Vraag twee:
Hoe kan ik op een eenvoudige manier ervoor zorgen dat alle pagina's binnen de webapp gebruik maken van deze code? Ik kan de code natuurlijk in een class hangen, maar dan zou ik nog steeds iedere gridview in de page_init moeten toevoegen. Ik zoek dus een manier om met een stukje generieke code die ik in iedere page_init kan hangen de eventhandler "AddPrevNextToGrid" aan alle gridviews te hangen. Moet dat door alle controls hangend aan het page-object heen te lopen en kijken of het toevallig een gridview is? Het lijkt me dat dit makkelijker kan.

Waarom dan geen usercontrol vraag je je wellicht af? Mijn opdrachtgever heeft in al zijn wijsheid besloten dat dat nou net niet is toegestaan. Zou slecht zijn voor het onderhoud. Argumenten dat het onderhoud er makkelijker op wordt, worden in de wind geslagen.

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 10:24

gorgi_19

Kruimeltjes zijn weer op :9

Ik heb ook al geprobeerd om de naam van de gridview als commandargument mee te geven, maar dan kan ik de gridview niet vinden met findcontrol.
Dan moet je zoeken, INCLUSIEF de $ tekens om zo de volledige naam (inclusief parent controls) te achterhalen.
Moet dat door alle controls hangend aan het page-object heen te lopen en kijken of het toevallig een gridview is? Het lijkt me dat dit makkelijker kan.
Wellicht dat je met een control adapter nog kan spelen. En usercontrols mogen blijkbaar niet, maar wellicht mogen custom (server) controls wel?

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • sopsop
  • Registratie: Januari 2002
  • Laatst online: 08:43

sopsop

[v] [;,,;] [v]

Topicstarter
gorgi_19 schreef op maandag 09 juli 2007 @ 23:45:
[..]
En usercontrols mogen blijkbaar niet, maar wellicht mogen custom (server) controls wel?
Nee, die zijn zo mogelijk nog moeilijker te onderhouden - aldus de opdrachtgever :'(

Verwijderd

Ik heb hier een stukje code welke het zoeken naar elementen makkelijker maakt, als je in een masterpage werkt. Werk je niet met masterpages dan heb je aan de fuctie FindControl() genoeg.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// <summary>
/// Looks for a control recursively up the control tree.  We need this because Page.FindControl
/// does not find the control if we are inside a masterpage content section.
/// </summary>
/// <param name="namingcontainer"></param>
/// <param name="controlName"></param>
/// <returns></returns>
    internal static class WebControlHelper
    {
        public static Control RecursiveFindControl(Control namingContainer, string controlId)
        {
            Control c = namingContainer.FindControl(controlId);

            if (c != null)
                return c;

            if (namingContainer.NamingContainer != null)
                return RecursiveFindControl(namingContainer.NamingContainer, controlId);

            return null;
        }
    }

  • sopsop
  • Registratie: Januari 2002
  • Laatst online: 08:43

sopsop

[v] [;,,;] [v]

Topicstarter
Ik heb het opgelost. Het bleek na wat doorvragen dat de opdracht gever niet wilde dat er gecompileerde sources in de site werden gebruikt. Dus geen custom controls in assembly (dll) vorm. Het bleek niet echt handig om de gridview uit te breiden in een usercontrol, maar een custom control was een eitje en die kun je ook gewoon met een namespace in de app_code zetten.

Dit is het customcontrol:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/// <summary>
/// Adds a previous/next button to a Numeric/NumericFirstLast paging type, and thus creating a
/// NumericFirstLastNextPrevious paging type.
/// </summary>
/// 

namespace CustomControls
{
    [ToolboxData(@"<{0}:CustomGridView runat=""server"" \>")]
    public class CustomGridView : GridView
    {
        CustomGridView grd;
        protected void PrevNextClick(object sender, System.Web.UI.WebControls.CommandEventArgs e)
        {
            if (e.CommandName == "PREV") {grd.PageIndex += -1;}
            else { grd.PageIndex += 1;}
            GridViewPageEventArgs gvpea = new GridViewPageEventArgs(grd.PageIndex);
            grd.OnPageIndexChanging(gvpea);
        }

        protected override void OnRowCreated(GridViewRowEventArgs e)
        {
            base.OnRowCreated(e);
            if (e.Row.RowType == DataControlRowType.Pager)
            {

                Table pagerTable = (Table)e.Row.Cells[0].Controls[0]; 
                grd = this;
                TableRow pagerRow = pagerTable.Rows[0];
                PagerSettings pagerSettings = grd.PagerSettings;
                int cellsCount = pagerRow.Cells.Count;

                if (pagerSettings.Mode == PagerButtons.Numeric || pagerSettings.Mode == PagerButtons.NumericFirstLast)
                {
                    //check whether previous button exists 
                    LinkButton btnPrev = new LinkButton();
                    btnPrev.Text = pagerSettings.PreviousPageText;
                    btnPrev.CommandName = "PREV";
                    if (grd.PageIndex <= 0) btnPrev.Visible = false;
                    btnPrev.Command += PrevNextClick;
                    TableCell PrevCell = new TableCell();

                    PrevCell.Controls.Add(btnPrev);
                    pagerRow.Cells.AddAt(0, PrevCell);

                    //check whether previous button exists 
                    LinkButton btnNext = new LinkButton();
                    btnNext.Text = pagerSettings.NextPageText;
                    btnNext.CommandName = "NEXT";
                    if (grd.PageIndex >= grd.PageCount - 1) btnNext.Visible = false;
                    btnNext.Command += PrevNextClick;
                    TableCell NextCell = new TableCell();
                    NextCell.Controls.Add(btnNext);
                    pagerRow.Cells.Add(NextCell);
                }
            }

        }
    }
}

In de web.config registreer je de CustomGridView als volgt (in vereenvoudigde vorm):
XML:
1
2
3
4
5
6
7
<system.web>
   <pages>
      <controls>
         <add namespace="CustomControls" tagPrefix="CC" />
      </controls>
   </pages>
</system.web>

En een de custom control zet je vervolgens als volgt in je aspx:
XML:
1
2
3
4
5
6
7
8
9
<CC:CustomGridView ID="CustomGridView1"
        runat="server" 
        AllowPaging="True" 
        DataSourceID="DataSource1" 
        PageSize="10" 
        PagerSettings-NextPageText="Volgende"
        PagerSettings-PreviousPageText="Vorige"
        PagerSettings-Mode="NumericFirstLast"    
        />

De vorige & volgende button krijgen in het bovenstaande geval dus de tekst "Vorige" en "Volgende". Deze custom control is op de paging na identiek aan de 'gewone' gridview. Het custom gedeelte van de CustomGridView wordt alleen gebruikt indien PagerSettings-Mode "NumericFirstLast" of "Numeric" is.

=edit= Ik heb nog een kleine wijziging gedaan in de PrevNextClick.

Het bleek namelijk dat het OnIndexChanging event niet werd afgeschoten. Indien je daar code achter hebt hangen werd die niet uitgevoerd. Nu wordt OnIndexChanging afgevuurd waardoor een pagechange hetzelfde wordt afgehandeld als bij een normale pagechange (door te klikken op een paginanummertje). Ongeacht of je custom pagechanging hebt geimplementeerd.

[ Voor 10% gewijzigd door sopsop op 13-07-2007 13:16 ]