2015-04-14 11 views
25

Quando uno ComboBox ha un numero elevato di elementi, il menu a discesa diventa scorrevole. Quando l'utente richiama questo menu a discesa e sposta il cursore del mouse per immettere i limiti del menu a discesa dal basso, il menu a discesa sposta immediatamente uno o più elementi nell'elenco (da goobering: accade anche quando si esce dai limiti tramite il bordo inferiore).Previene lo scorrimento quando il mouse entra nel menu a discesa WPF ComboBox

Questo scorrimento non è intuitivo, in quanto l'elenco non scorre verso l'alto quando si inseriscono i limiti dall'alto.

Come disattivare il comportamento di scorrimento automatico?

In Visual Studio questo comportamento può essere osservato tramite il menu a discesa elemento sulla barra di navigazione del codice dell'editor (CTRL +F2).

+2

Per chiarire il comportamento, questo sembra a fuoco ogni volta che il cursore si sposta sopra il limite più basso della casella combinata a discesa * in entrambi i direzione *, dall'alto verso il basso o dal basso verso l'alto. – goobering

+0

Quale versione di .NET è in esecuzione? – David

+0

@Aravol .NET 4.5 – JoeGaggler

risposta

12

One Il modo per risolverlo è utilizzare un comportamento (o piuttosto una proprietà associata al comportamento) per iscriversi all'evento RequestBringIntoView dello ComboBoxItems e quindi impostare RequestBringIntoViewEventArgs.Handled su true. Questo può essere fatto anche su piccola scala usando EventSetter e codebehind.

<Style TargetType="ComboBoxItem">      
    <EventSetter Event="RequestBringIntoView" Handler="OnRequestBringIntoView"/> 
</Style> 

private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) 
{ 
    //Allows the keyboard to bring the items into view as expected: 
    if (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up)) 
     return;    

    e.Handled = true;    
} 

Modifica

ho trovato che è possibile ottenere lo stesso effetto gestendo l'evento RequestBringIntoView sul ItemsPanel piuttosto che gli oggetti stessi. Ma lo stesso risultato:

<ComboBox.ItemsPanel> 
    <ItemsPanelTemplate> 
     <StackPanel RequestBringIntoView="OnRequestBringIntoView"/> 
    </ItemsPanelTemplate> 
</ComboBox.ItemsPanel> 
+0

Non sul 'ComboBox' stesso - come è stato scritto deve essere nel' ComboBoxItem'.Puoi mettere insieme una demo rapida che mostra che funziona aggiungendo esplicitamente 'ComboBoxItems' a un comboBox e collegandoti al loro evento. Funziona. –

+1

Vedo. Questo codice evita lo scorrimento degli eventi del mouse. Sarebbe necessaria più logica per consentire lo scorrimento degli eventi della tastiera come l'utente si aspetterebbe, ma questo codice risponde alla mia domanda originale. – JoeGaggler

+1

@JoeGaggler Ho scoperto che funziona anche dall'evento 'ItemsPanel' - che riduce il numero di eventHandler che sono collegati. –

4

Da quello che posso dire questo sembra essere causato dal fatto che gli elementi in fondo alla luce sono "parzialmente visualizzati", dove un oggetto viene troncato dal contenitore. Quando il mouse si sposta su un oggetto parziale come questo, WPF scorre l'intero oggetto in vista, che a volte può lasciare un altro elemento parziale in fondo.

In Winform può essere risolto impostando .IntegralHeight, ma in WPF tale proprietà non esiste. Se tutti gli elementi della tua casella combinata hanno la stessa altezza puoi legare l'altezza dell'elenco della casella combinata a un multiplo dell'altezza dell'oggetto, ad esempio visualizzare 10 x 20px voci alte, impostarlo su 200.

+0

Questa è una grande teoria, ma non sembra funzionare quando ho provato. Sono stato in grado di impostare esplicitamente l'altezza dell'elemento utilizzando la proprietà 'ItemTemplate', quindi impostare' MaxDropDownHeight' come parte integrante dell'altezza dell'oggetto. Il comportamento si è verificato ancora quando si sposta il mouse sul bordo del menu a discesa. Ho anche provato ad aggiustare l'altezza di +/- 1px per assicurarmi che non ci fosse un problema "off-one". – JoeGaggler

0

La risposta selezionata da Andrew Hanlon evita che l'elenco scorra fino all'elemento selezionato all'apertura. Avevo anche aggiungere questo nel gestore di eventi ("lista" è il ComboBox):

private void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) 
{ 
    //Allows the keyboard to bring the items into view as expected: 
    if (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up)) 
     return; 

    // Allows to bring the selected item into view: 
    if (((ComboBoxItem)e.TargetObject).Content == list.SelectedItem) 
     return; 

    e.Handled = true; 
} 
Problemi correlati