Repeater e controllo su valore di un Image dentro al repeater

lunedì 10 marzo 2008 - 21.15

ravalon Profilo | Expert

Salve, ho un repeater dove disegno un controllo IMAGE come da codice


<asp:Image ID="imgFotoGestori" runat="server" ImageUrl=<%#DataBinder.Eval(Container.DataItem, "Foto")%> />

Devo controllare per ogni record che il valore BINDATO della foto (che fa da URL dell'immagine) non sia VUOTO, in tal caso devo passare una stringa che punta ad una IMMAGINE DI DEFAULT...

Purtroppo il controllo me lo fa , da codice, solo per il primo record e gli altri no....

Ecco il codice usato...

Dim imgFotoGestori As Image = RepeaterChiSiamo.Items(0).FindControl("imgFotoGestori")

If imgFotoGestori.ImageUrl.ToString = "" Then
imgFotoGestori.ImageUrl = ImgPath & "NoFotoGestore.gif"
End If

E' Evidente che se lo metto nel LOAD della PAGE me lo fa una sola volta, ma come faccio a farglielo fare ogni volta ? L'ho messo in ogni evento possibile dell'oggetto Repeater ma non mi funziona....
cosa sbaglio ??

rossimarko Profilo | Guru

Ciao,

la soluzione migliore a mio avviso è quella di agganciare l'evento ItemDataBound del repeater e popolare il controllo immagine in base al dato contenuto nel record che sta facendo il bind della riga. L'evento ItemDataBound viene scatenato ogni volta che un elemento del repeater viene popolato.

Supponendo ad esempio che il datasource del tuo repeater sia una dataTable, il codice da inserire nell'evento è il seguente:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Ovviamente dovrai adattarlo alle tue esigenze per quanto riguarda i path delle immagini .

PS: all'interno della pagina aspx non sarà più necessario popolare l'immagine in quanto lo fai già da codice. In questo caso devi semplicemente definirla senza popolarla:
<asp:Image ID="imgFotoGestori" runat="server" />

Marco

ravalon Profilo | Expert

Ho provato come hai detto, mi sembrava una buona strada ma credo ci sia qualche problema perchè mi da errore sull'indice, dice che è fuori range...

Ho usato questo codice nell'evento PRE_RENDER....so che è un lavoro poco pulito ma intanto funziona


///////////////////////////////////////////////////////////
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender

Dim i As Integer
For i = 0 To RepeaterChiSiamo.Items.Count - 1
Dim imgFotoGestori As Image = CType(RepeaterChiSiamo.Items(i).FindControl("imgFotoGestori"), Image)

If String.IsNullOrEmpty(imgFotoGestori.ImageUrl.ToString) Then
imgFotoGestori.ImageUrl = ImgPath & "NoFotoGestore.gif"
End If
Next
End Sub
///////////////////////////////////////////////////////////

chiaramente ho lasciato valorizzato il codice della pagina ASPX per quanto riguarda la proprietà ImageUrl

se hai qualche idea sul come mai mi dia quell'errore preferirei fare come dicevi tu...

rossimarko Profilo | Guru

>Ho provato come hai detto, mi sembrava una buona strada ma credo
>ci sia qualche problema perchè mi da errore sull'indice, dice
>che è fuori range...
>

Ciao,

puoi mandare la riga che da errore così controlliamo?

Per l'evento PreRender sarebbe meglio non usarlo come hai fatto tu, perchè in questo modo fai due cicli, uno per popolare la griglia e uno successivo nel prerender per modificare il contenuto del controllo immagine.
Mettendo il codice nell'itemDataBound invece ti agganci al ciclo di popolamento della griglia ed è quindi più efficiente.

Marco

ravalon Profilo | Expert

Infatti è per quello che vorrei fare come dici tu....

l'errore è questo

////////////////////////
Riferimento a un oggetto non impostato su un'istanza di oggetto.
Descrizione: Eccezione non gestita durante l'esecuzione della richiesta Web corrente. Per ulteriori informazioni sull'errore e sul suo punto di origine nel codice, vedere l'analisi dello stack.

Dettagli eccezione: System.NullReferenceException: Riferimento a un oggetto non impostato su un'istanza di oggetto.

Errore nel codice sorgente:
////////////////////////////

Il codice usato è il seguente

////////////////////////////
Dim imgFotoGestori As Image = CType(e.Item.FindControl("imgFotoGestori"), Image)

If imgFotoGestori.ImageUrl.ToString="" Then
imgFotoGestori.ImageUrl = ImgPath & "NoFotoGestore.gif"
End If
///////////////////////////

rossimarko Profilo | Guru

>
>Il codice usato è il seguente
>
>////////////////////////////
>Dim imgFotoGestori As Image = CType(e.Item.FindControl("imgFotoGestori"),
>Image)
>
> If imgFotoGestori.ImageUrl.ToString="" Then
>imgFotoGestori.ImageUrl = ImgPath & "NoFotoGestore.gif"
> End If
>///////////////////////////
>

Il fatto che dia una System.NullReferenceException vuol dire che ci deve essere un oggetto non valorizzato (= Nothing). Vedendo il codice mi viene da dire che non trovi il riferimento all'immagine
e.Item.FindControl("imgFotoGestori")
però mi sembra molto strano, visto che mi dici che mettendola nel prerender funziona. Nella segnalazione di errore dovrebbe dirti anche la riga di codice in cui si verifica l'eccezione, puoi postarla?

Un'altra cosa, mi confermi che il controllo è un repeater e non un datalist? Se fosse un datalist l'evento verrebbe scatenato anche per l'header e in quel caso sarebbe corretto che la funzione FindControl ritorni nothing.

ravalon Profilo | Expert

Si ti confermo che si tratta di un repeater, anzi ti posto anche il codice di marckup...non sia mai che l'errore è li

////////////////////////////////////////
<asp:Repeater ID="RepeaterChiSiamo" runat="server" EnableViewState=false>
<HeaderTemplate>
</HeaderTemplate>

<ItemTemplate>
<table width="100%" class="TableBase" cellspacing="1" cellpadding ="0">
<tr>
<td width="30%" align="left" valign="top" class="BGGrigino">
<asp:Image ID="imgFotoGestori" runat="server" ImageUrl=<%#imgpath & DataBinder.Eval(Container.DataItem, "Foto")%> />
</td>

<td width="70%" valign="top" class="BGGrigino">
<img src=<%#imgpath & "freccia.gif"%>/>
<asp:Label ID="litNome" runat="server" CssClass="TestiRossiBIG" Text=<%#UCase(DataBinder.Eval(Container.DataItem, "Nome"))%>></asp:label>
<br />
<asp:Label ID="litRuolo" runat="server" CssClass="TestiVerdiMedi" Text=<%#UCase(DataBinder.Eval(Container.DataItem, "Ruolo"))%>></asp:label>
<br /><br />
<asp:Label ID="litAttivita" runat="server" CssClass="TestiMedi" Text=<%#DataBinder.Eval(Container.DataItem, "Attivita")%>></asp:label>

</td>
</tr>
</table>

</ItemTemplate>

<FooterTemplate>

</FooterTemplate>
</asp:Repeater>
///////////////////////////////////////////

La riga dell'errore è la 54, che corrisponde al seguente codice

If imgFotoGestori.ImageUrl.ToString = "" Then

rossimarko Profilo | Guru

>
>La riga dell'errore è la 54, che corrisponde al seguente codice
>
>If imgFotoGestori.ImageUrl.ToString = "" Then
>


Controlla in debug se la variabile imgFotoGestori è = nothing.

PS: non serve il tostring dell'imageUrl perchè è gia una stringa. Puoi scrivere semplicemente
If imgFotoGestori.ImageUrl = "" Then

ravalon Profilo | Expert

Si esatto...da degub della immediate windows ottengo questo

L'oggetto a cui si fa riferimento ha valore "Nothing".

rossimarko Profilo | Guru

Ho visto cche nel codice aspx hai inserito l'HeaderTemplate.
Per evitare l'errore devi inserire il codice dell'itemDataBound all'interno di un if che controlli il tipo dell'item:

If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then 'Preleva riferimento all'immagine Dim img As Image = CType(e.Item.FindControl("imgFotoGestori"), Image) 'Riferimento alla riga utilizzata come sorgente dati Dim drv As DataRowView = CType(e.Item.DataItem, DataRowView) 'Percorso dell'immagine Dim strPath As String = drv("Foto").ToString() If String.IsNullOrEmpty(strPath) Then img.ImageUrl = "~/ImmagineVuota.jpg" Else img.ImageUrl = strPath End If End If

altrimenti il find control all'interno di un item di tipo Header non trova niente (come succedeva nel tuo caso).

ravalon Profilo | Expert

Grandissimo !!

Il problema era proprio quello....ho tolto l'headertemplate tanto non mi serviva....e funziona alla grande...

GRAZIE !

alba Profilo | Newbie

scusate, ma ho lo stesso problema
Ho letto i vostri post, la mia unica difficolta' sta nel fatto che per riempire il repeater uno un datareader, e quando faccio il cast per recuperare il datarowview, mi ritorna un valore nullo....avete qualche idea? grazie

rossimarko Profilo | Guru

Se usi un datareader il dataitem non è di tipo datarowview ma di tipo dbdatarecord

Qui trovi alcuni esempi nella sezione "Casting di tipo esplicito"
http://support.microsoft.com/kb/307860/it

Un'altra cosa a cui stare attenta è che l'evento che hai agganciato sia l'ItemDataBound
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

alba Profilo | Newbie

grazie infinite! Funziona a meraviglia!!!
nel frattempo avevo adottato una soluzione usando un datatable, ma ovviamente era piu' lenta
grazie ancora
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5