2009-05-25 10 views
19

Sto usando una listbox nella mia applicazione di moduli Windows C# 2.0. Il metodo per popolare la casella di riepilogo èCome prevenire l'evento ListBox.SelectedIndexChanged?

private void PopulateListBox(ListBox lb, ReportColumnList reportColumnList) 
    { 
     lb.DataSource = reportColumnList.ReportColumns; 
     lb.DisplayMember = "ColumnName"; 
     lb.ValueMember = "ColumnName"; 
    } 

Tuttavia, quando si esegue il metodo si chiama anche il gestore eventi SelectedIndexChanged della casella di riepilogo, anche se io non sono la creazione l'indice selezionato nel metodo di cui sopra. Come posso impedire che il gestore di eventi SelectedIndexChanged venga chiamato per il codice sopra?

Voglio che l'evento venga chiamato solo quando l'utente effettua le selezioni nel ListBox. O c'è qualche altro evento che è solo per l'utente che seleziona gli oggetti della lista usando il click del mouse?

In un'altra nota, anche se l'utente fa clic su un'area vuota nella casella di riepilogo, l'evento SelectedIndexChanged viene generato. Quindi mi chiedo quanto sia diverso dall'evento MouseClick?

+1

Per la maggior parte, non si può impedire che un oggetto da sollevare un evento .. Si può solo scegliere di smetti di ascoltare le notifiche degli eventi. – Gishu

+0

Intendevo se potevo in qualche modo impedire quella parte del mio codice, che spara all'evento. Ma come possiamo vedere non c'è nulla che io possa fare come tutte e tre le righe nel PopulateListBox() sono reqd :) –

risposta

15

è possibile popolare la casella di riepilogo utilizzando lb.Items.AddRange() invece di impostare l'origine dati. Oltre a non attivare SelectedIndexChanged, anche questo non pre-seleziona il primo elemento.

lb.Items.Clear(); 
lb.Items.AddRange(reportColumnList.ReportColumns.ToArray()); 
+1

Sì ... questo è esattamente quello che volevo. Ho cambiato il mio codice secondo la tua risposta e funziona come un incantesimo :) Grazie mille, Kim !!! –

18

Ci sono tre modi per farlo.

A) Non agganciare all'evento SelectedIndexChanged finché DOPO non hai chiamato questo metodo.

B) Avere un booleano privato nella classe inizialmente impostato su true. All'inizio del tuo metodo PopulateListBox, impostalo su false e alla fine riportalo su true. Nel gestore di eventi per SelectedIndexChanged, se il flag è falso, basta tornare indietro e non fare nulla.

C) All'inizio del metodo PopulateListBox, sganciare dall'evento (this.listbox1.SelectedIndexChanged - = myMethod;) e quindi, prima che il metodo venga eseguito, reinserire quell'evento.

+0

Grazie per la risposta. Tuttavia, invece dei passaggi precedenti, cosa succede se utilizzo l'evento MouseClick per gestire le modifiche alla selezione dell'utente? In questo modo l'evento MouseClick verrà generato solo se la selezione dell'utente cambia e non verrà richiamata quando viene chiamato PopulateListBox(). Ci sono degli svantaggi nell'usare l'evento MouseClick in questo scenario? L'ho provato e funziona bene, anche se mi piacerebbe conoscere alcuni bug nascosti che potrei affrontare in futuro a causa di questo. –

+0

Impossibile utilizzare l'approccio MouseClick. Motivo: per la casella di riepilogo MultiExtended, quando viene attivato il clic del mouse, anche se ho selezionato più di un elemento, il conteggio degli indici selezionati non riflette questo. Solo quando viene chiamato SelectedIndexChanged, ottengo un conteggio corretto. –

+0

Di solito vado con l'opzione A. +1 – Cerebrus

1

È necessario tenere presente che anche se non si gestisce l'evento, il primo elemento nell'elenco verrà comunque selezionato automaticamente quando si assegna la proprietà DataSource. Per costringere l'utente a effettuare una selezione, è necessario deselezionare l'elemento selezionato automaticamente.

Se il gestore di eventi SelectedIndexChanged attiva alcune funzionalità quando si seleziona un elemento, è possibile che si desideri bloccare l'esecuzione. Un modo per farlo è quello di tenere traccia del fatto che il codice stia attualmente compilando la lista o meno. Se l'evento SelectedIndexChanged viene attivato mentre la casella di riepilogo viene popolata, è possibile evitare di eseguire queste azioni:

private bool _populating = false; 
private void PopulateListBox(ListBox lb, ReportColumnList reportColumnList) 
{ 
    _populating = true; 
    lb.DataSource = reportColumnList.ReportColumns; 
    lb.DisplayMember = "ColumnName"; 
    lb.ValueMember = "ColumnName"; 

    // clear the automatically made selection 
    lb.SelectedIndex = -1; 
    _populating = false; 
} 

private void ListBox_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (!_populating) 
    { 
     // perform the action associated with selecting an item 
    } 

} 
6

C'è una risposta più semplice a questo problema: Un seguente snippet di codice può suggerire il lavoro intorno.

lstBxState.SelectionMode = SelectionMode.None; 
lstBxState.DataSource = lstStates; 
lstBxState.ValueMember = "StateId"; 
lstBxState.DisplayMember = "StateName"; 
lstBxState.ClearSelected(); 
lstBxState.SelectionMode = SelectionMode.One; 

Ciò significa che è sufficiente impostare la modalità di selezione su "Nessuno" e fortunatamente Data Bind il controllo. Poi vai avanti e cambia la modalità in quella richiesta (qui l'ho cambiata in Uno, puoi selezionare anche Multiple).

+0

'System.Web.UI.WebControls.ListSelectionMode' non contiene una definizione per 'Nessuno' – Homer

+1

Questa domanda riguarda Windows Form, quello spazio dei nomi è per i controlli ASP.NET. – KyleMit

1

All'interno del metodo SelectedIndexChanged, proprio pit in un'istruzione if che dice, se SelectedIndex == -1 fare niente altro, fare quello che vuoi fare in questo metodo, probabilmente non il codice più efficiente, ma ha funzionato per me :)

0
private void PopulateListBox(ListBox lb, ReportColumnList reportColumnList) 
{ 

    lb.SelectedIndexChanged -= this.*MethodnamewhichhandlesthisEvent*; //unset eventhandler 

    lb.DataSource = reportColumnList.ReportColumns; 
    lb.DisplayMember = "ColumnName"; 
    lb.ValueMember = "ColumnName"; 

    lb.SelectedIndexChanged += this.*MethodnamewhichhandlesthisEvent*; //set the eventhandler 
} 

In pratica, rimuovere il delegato dall'evento e quindi aggiungere una volta terminato.

0

La mia situazione potrebbe essere unica, ma la posterò qui nel caso in cui aiuti qualcuno.

Stavo facendo il Items.AddRange per popolare il mio ListBox invece di associazione. Non so perché, ma su PostBack, il SelectedIndex passava da -1 a 0. Ciò potrebbe essere dovuto al fatto che il mio ListBox era SelectionMode="Single".

La mia difficoltà è stato quello di impostare manualmente il SelectedIndex a 0 invece di -1 dopo la popolazione:

listBox.Items.AddRange(items); 
listBox.SelectedIndex = 0;