Monthly Archives: September 2010

Sor megszerzése GridView RowCommandnál

Ha egy GridView valamelyik oszlopába gombokat teszünk, akkor a RowCommand esemény nagyon praktikus, mert az eseménykezelő CommandName és CommandArgument tulajdonságai segítségével könnyen meg tudjuk vizsgálni, hogy melyik sorban, melyik gombra kattintott a felhasználó. A CommandArgument tulajdonságot általában az adott rekord kulcs oszlopához szoktuk kötni, hogy az adott rekordra könnyen tudjunk hivatkozni. De mi van akkor, ha a GridView adott sorára is hivatkozni szeretnénk?

Sajnos az eseménykezelő nem tartalmaz ilyen paramétert és ha teljesen egyedi eseményünk van, akkor ezt a GridViewból sem tudjuk kinyerni. Választhatjuk azt a megoldást, hogy a hagyományos Buttonból származtatunk egy saját osztályt, amit kibővítünk egy egyszerű RowIndex tulajdonsággal:

  public int RowIndex
  {
    get
    {
      object obj = this.ViewState[ "RowIndex" ];
      return obj != null ? (int) obj : -1;
    }
    set
    {
      this.ViewState[ "RowIndex" ] = value;
    }
  }

A következő lépés, hogy a GridViewban saját template oszlopot használunk és ott adatkötéssel beállítjuk ezt a tulajdonságot:

  <asp:TemplateField>
    <ItemTemplate>
      <Demo:MyButton runat="server" 
        Text="Csináld!" 
        CommandArgument='<%# Eval("ID") %>'
        RowIndex='<%# Container.DataItemIndex %>' />
    </ItemTemplate>
  </asp:TemplateField>

A gridhez tartozó RowCommand eseménykezelőben így már könnyen megkaphatjuk a sor indexét:

  private void OnRowCommand( object sender, GridViewCommandEventArgs e )
  {
    int rowIndex = ( e.CommandSource as MyButton ).RowIndex;
    // GridView.Rows[ rowIndex ] ...     
  }

Innen kezdve a GridView.Rows gyűjteményt megindexelve könnyen el tudjuk érni a kívánt sort és például megváltoztathatjuk a háttérszínét, hogy visszajelzést adjunk a felhasználónak.

Technorati-címkék:

Advertisements

CDN kontra IntelliSense

A CDN használata a felhasználói élmény szempontjából szép dolog, de mivel az offline fejlesztést megkeseríti, célszerű a használatát legalább egy web.config beállításhoz kötni. Ám ha code behindból szúrjuk be a fejlécbe a <script> tag-et, akkor nem lesz IntelliSense. De hogyan lehet olyan markupot írni, ami csak a Visual Studioban szúr be egy helyi szkript fájlra mutató hivatkozást?

Így – vagyis pontosabban ez kiveszi az adott sort, ha nem VS-ban fut, de az eredmény ugyanaz:

    <% 
        #pragma warning disable 162
        if( false ) 
        { 
    %>
            <script type="text/javascript" src="/Static/jquery-1.4.2.js"></script>
    <% 
        }
        #pragma warning restore 162
    %>

A #pragma sorok azért kellenek, hogy a C# fordító ne pattogjon CS0162 Unreachable code detected hibaüzenettel.

Több vezérlő validálása kliens oldalon

Gyakran előforduló feladat, hogy egy vezérlő értékét nem önmagában kell validálnunk, hanem más vezérlők értékével együtt kell érvényesnek lennie. Sajnos az ASP.NET beépített validátorai közül egyedül a CompareValidator képes erre, aminek azonban végesek a képességei. Szerver oldalon még könnyen megbirkózunk a feladattal, de hogyan oldjuk meg, hogy a kliens oldali validáló függvényünk bármelyik vezérlő értékének változása esetén lefusson?

Bár nem kifejezetten erre találták ki, célszerű egy CustomValidatorból kiindulni, hogy a kódunk szerves része legyen a standard validálási mechanizmusnak, és természetesen állítsuk be a ClientValidationFunction paramétert is. Az első bökkenő ott jön, hogy a ControlToValidate tulajdonságban csak egyetlen vezérlőt adhatunk meg, és így a kliens oldali ellenőrző függvényünk is csak egy vezérlő értékét kapja meg. Itt kell egy kis trükk: expando attribútumként csapjuk hozzá a validálandó vezérlők (itt az egyszerűsített példában txtStartDate és txtEndDate) kliens oldali ID-jait a validátor vezérlőhöz (cvDateOrder):

  ScriptManager.RegisterExpandoAttribute( 
this, this.cvDateOrder.ClientID, "StartDateID", this.txtStartDate.ClientID, false ); ScriptManager.RegisterExpandoAttribute(
this, this.cvDateOrder.ClientID, "EndDateID", this.txtEndDate.ClientID, false );

A következő lépés, hogy a kliens oldali validáló keretrendszer eseménykezelésébe befűzzük mindkét vezérlőt az ASP.NET beépített (bár nem éppen agyondokumentált) JavaScriptes ValidatorHookupControl függvényével. Ehhez mindenképp JavaScriptre lesz szükségünk, aminek el kell érnie a validátor vezérlőt, ezért adjuk át neki a kliens oldali azonosítóját:

  string init = String.Format( "onDateFilterInit('{0}');", this.cvDateOrder.ClientID );
  ScriptManager.RegisterStartupScript( 
this.Page, this.Page.GetType(), "onDateFilterInit", init, true );

  function onDateFilterInit(strValID) {
    var $cvDateOrder = $("#" + strValID);
    ValidatorHookupControl($("#" + $cvDateOrder.attr("StartDateID"))[0], $cvDateOrder[0]);
    ValidatorHookupControl($("#" + $cvDateOrder.attr("EndDateID"))[0], $cvDateOrder[0]);
  }

Így már mindkét vezérlő értékének változása esetén meg fog hívódni a validáló függvényünk. Ott pedig ugyanígy az expando attribútumon keresztül megszerezhetjük a két ellenőrizendő értéket:

  function onDateFilterValidate(source, args) {
    // Megkeressük a validátor vezérlőt.
    var $cvDateOrder = $("#" + source.id);

    // Megszerezzük a validálandó vezérlők azonosítóit, majd azon keresztül az értékeit.
    var startDate = $("#" + $cvDateOrder.attr("StartDateID")).val();
    var endDate = $("#" + $cvDateOrder.attr("EndDateID")).val();
    // Értékek vizsgálata és args.IsValid beállítása...
  }

Technorati-címkék: ,,,