Domanda

alt text http://img3.imageshack.us/img3/1488/advancedsearch. png

Sto creando una ricerca avanzata " interfaccia in un'applicazione ASP.NET. Non ho bisogno di SO per scrivere questa cosa per me, ma sono bloccato su un problema specifico riguardante i controlli dinamici e ViewState. Vorrei una direzione su come affrontare questo. Ecco la mia situazione:

Ingredienti:

  • Un insieme funzionale di oggetti API che rappresentano entità, campi e ricerche, che gestisce la costruzione di una ricerca, la generazione di SQL e la restituzione dei risultati. Quindi è tutto curato.
  • ASP.NET 3.5

Funzionalità dell'interfaccia desiderata:

(1) Al caricamento della pagina iniziale, l'interfaccia ottiene un oggetto di ricerca preconfigurato con un set di oggetti SearchCriterion. Li lega in una serie di controlli (vedi immagine sopra.)

  • Alcuni elementi di ricerca sono più semplici, come:

    Campo (DropDownList) | Operatore (elenco a discesa) | Valore (TextBox)

  • I controlli del criterio di ricerca per alcuni tipi di campo hanno informazioni importanti archiviate in viewstate, come:

    Campo (DropDownList) | Operatore (elenco a discesa) | Valore (elenco a discesa) in cui il "Valore" l'elenco a discesa è popolato da una query del database.

  • Alcuni campi sono ricerche in altre entità, il che provoca una catena di selettori di campo, come:

    Campo (DropDownList) Campo (DropDownList) | Operatore (elenco a discesa) | Valore

(2) L'utente modifica la ricerca per:

  • Aggiunta e rimozione di criteri di ricerca facendo clic sui rispettivi pulsanti
  • Configurazione dei criteri esistenti modificando il campo, l'operatore o il valore. Le modifiche al campo o all'operatore richiederanno al controllo di riconfigurarsi modificando gli operatori disponibili, modificando il "Valore". inserisci il controllo in un tipo diverso o aggiungi / rimuovi DropDownLists dai "Campi" se i campi di tipo Ricerca sono selezionati / non selezionati.

(3) Infine, l'utente preme " Cerca " per vedere i loro risultati.

Il problema:

Come probabilmente già saprai se stai rispondendo a questa domanda, i controlli aggiunti dinamicamente alla pagina scompaiono al postback. Ho creato un UserControl che manipola la raccolta di controlli e compie ordinatamente il passaggio (1) sopra, come puoi vedere nell'immagine allegata. (Non sono preoccupato per lo stile a questo punto, ovviamente.)

Comunque su Postback, i controlli sono tutti spariti e il mio oggetto API di ricerca è sparito. Se riuscissi a far sì che la raccolta di controlli generata dinamicamente funzionasse bene e rimanesse in ViewState, avrei potuto esaminare i controlli sul postback, ricostruire l'oggetto di ricerca, quindi gestire gli eventi di controllo in modo accurato.

Soluzioni possibili

  • Potrei rendere l'oggetto di ricerca serializzabile e memorizzarlo in viewstate. Quindi al caricamento della pagina ho potuto afferrarlo e ricostruire la raccolta di controllo al momento del caricamento della pagina. Tuttavia, non sono sicuro che questo funzionerebbe bene con i controlli che generano eventi, e cosa succede al viewstate degli elenchi a discesa che contengono dati dal database? Potrei recuperarli? È altamente indesiderabile per me dover ripetere la query del database su ogni postback.

  • Potrei sviluppare un controllo server personalizzato ( vedere questo link ) per questo tipo di cose ... ma questo è un nuovo argomento per me e richiederebbe un po 'di apprendimento, inoltre non sono del tutto sicuro se un controllo server personalizzato funzionerebbe più bene con raccolte di controlli non fissi. Qualcuno lo sa?

  • Stavo pensando che avrei potuto essere in grado di farlo utilizzando i controlli di banca dati - ad esempio potrei legare la mia raccolta di criteri a un ripetitore che ha una raccolta di controlli fissa (forse nascondere i controlli "valore" non utilizzati , utilizza un ripetitore interno per gli elenchi a discesa "Campo". Quindi tutte le informazioni rimarrebbero in ViewState ... giusto?

  • Qualsiasi nuova idea sarebbe molto apprezzata.

grazie per l'aiuto. b.Fandango

È stato utile?

Soluzione

Ho programmato per circa un giorno e ho fatto in modo che funzionasse magnificamente usando la terza opzione che ho suggerito nella mia domanda: controlli di database di vecchia scuola. In realtà ho pensato all'idea solo quando sono stato costretto a scrivere la domanda in dettaglio - non ti succede sempre?

Ho inserito il mio SearchCriterionControl in un asp: Repeater e l'ho associato alla mia collezione di oggetti. Per Field Chooser ho inserito un asp: DropDownList all'interno di un asp nidificato: ripetitore e associato l'array Field a quello. Tutto funziona magnificamente, mantiene lo stato, in realtà richiede pochissimo codice. Quindi non ho mai dovuto aggiungere dinamicamente controlli alla pagina, grazie al cielo.

Grazie per i tuoi suggerimenti, Ender, Matt e andrewWinn.

Altri suggerimenti

Dato che nessun altro ci ha provato per 2 ore, lancerò il mio cappello sul ring con una soluzione che non si basa affatto sul viewstate (o sul modello di postback ASP.NET).

Che cosa succede se hai preso tutti i valori di input con jQuery e invece di fare un post-back hai fatto un post sulla pagina (o una nuova pagina results.aspx)? Oppure, potresti rendere l'intera cosa asincrona e fare una richiesta Ajax contro un metodo web, ottenere dati nutriti e popolare sul lato client secondo necessità?

La cosa sfortunata qui è che devi ricostruire quale tipo di controlli sono stati usati per capire come costruire la tua query di ricerca poiché quei dati non saranno passati con il viewstate. Ma immagino che avresti già dovuto fare una sorta di traduzione dei tuoi dati di input in un modulo di query comunque.

Leggi qui per ulteriori informazioni sull'uso di jQuery per colpire un metodo di pagina ASP.NET. Ricorda: i metodi della pagina devono essere statici (è una supervisione semplice).

Non sono sicuro di cosa stai facendo sul lato server per costruire la tua query, ma raccomanderei fortemente di LINQ. Ho fatto una ricerca "simile" avanzata simile in precedenza, e dopo alcuni tentativi diversi ho scoperto che LINQ era uno strumento meraviglioso per questo problema, indipendentemente dal fatto che stavo colpendo SQL con LINQtoSQL o semplicemente colpendo una raccolta di oggetti in memoria.

Funzionava così bene perché 1) LINQ è l'esecuzione differita e 2) Una query LINQ restituisce un altro oggetto interrogabile. L'implicazione qui è che puoi mettere insieme le tue query LINQ mentre le costruisci dal tuo input, invece di dover fare una singola traduzione di clausole voluminose in SQL o qualunque backstore stai usando (uno dei miei tentativi è stato quello di costruire clausole SQL con stringhe, ma ancora passando i dati di input tramite SQLParameters per la protezione dell'iniezione SQL - era disordinato e complicato quando LINQ realizzato a mano era ordini di grandezza più facili da capire e implementare).

Ad esempio:

List<string> data; // or perhaps your a DB Context for LINQtoSQL?

var query = data.Where(item => item.contains("foo"));

if( {user supplies length search option} )
    query = query.Where(item => item.Length < 5);

// etc, etc.

// LINQ doesn't do anything until the query is iterated, at which point
// it will construct the SQL statement without you worrying about details or parameter binding
foreach(string value in query)
    ; // do something with the results

A causa dell'esecuzione differita e del tipo restituibile interrogabile, è possibile concatenare le query LINQ a questa espressione per tutto il giorno e lasciarle preoccupare dei dettagli dell'implementazione (come la conversione in una query SQL) al momento dell'esecuzione.

Non posso fornirti i passi esatti che dovrai fare, ma consiglio vivamente di esaminare il ciclo di vita della pagina asp.net. Una volta ho creato un controllo utente come DLL. Ho dovuto acquisire i dati di postback in fasi specifiche del ciclo di vita e ricreare e ricollegare i dati in altre fasi. Inoltre thinkgs come viewstate sono disponibili solo in determinati punti. So che ho dovuto sovrascrivere On_init, On_prerender e alcuni altri metodi.

Mi dispiace non potrei essere più di aiuto, ma non ho il codice con me (è con un vecchio datore di lavoro). Spero che questo aiuti.

Se si aggiungono i controlli alla struttura dei controlli in modo dinamico, è necessario aggiungerli anche sul pacchetto postale. Basta chiamare il metodo che crea il controllo su Page_Load o Page_Init e i controlli dovrebbero rimanere sulla pagina al postback.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top