2015-04-14 7 views
25

Wenn eine ComboBox eine große Anzahl von Elementen hat, wird seine Dropdown-Liste scrollbar. Wenn der Benutzer dieses Dropdown aufruft und den Mauszeiger bewegt, um die Grenzen des Dropdown-Menüs von unten einzugeben, scrollt das Dropdown-Menü sofort einen oder mehrere Elemente in der Liste (von goobering: passiert auch, wenn die Grenzen über die untere Kante verlassen werden).Verhindern Scrollen, wenn Maus WPF ComboBox dropdown

Dieses Scrollen ist nicht intuitiv, da die Liste beim Eingeben der Grenzen von oben nicht nach oben scrollt.

Wie können wir das automatische Scrollverhalten deaktivieren?

In Visual Studio kann dieses Verhalten über das Drop-Down-Mitglied auf dem Code-Editor in der Navigationsleiste (CTRL +F2) beobachtet werden.

+2

das Verhalten Um zu klären, scheint dies zu feuern, wenn der Cursor in der untersten Grenze des ComboBox Dropdown * bewegt sich entweder über Richtung *, von oben nach unten oder von unten nach oben. – goobering

+0

Welche Version von .NET laufen Sie? – David

+0

@Aravol .NET 4.5 – JoeGaggler

Antwort

12

Eins Um dies zu lösen, verwenden Sie ein Behaviour (oder eher eine behaviour-ähnliche Attached-Eigenschaft), um das -Ereignis der ComboBoxItems zu subskribieren und dann die RequestBringIntoViewEventArgs.Handled auf true zu setzen. Dies kann auch in einem kleinen Maßstab mit einem EventSetter und Codebehind durchgeführt werden.

<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;    
} 

bearbeiten

fand ich, dass Sie die RequestBringIntoView Veranstaltung durch die Handhabung auf der ItemsPanel die gleiche Wirkung erhalten können, anstatt den Einzelteilen selbst. Aber dasselbe Ergebnis:

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

Nicht auf der 'ComboBox' selbst - wie geschrieben wurde, muss es an der' ComboBoxItem' sein.Sie können eine kurze Demo erstellen, die zeigt, dass es funktioniert, indem Sie 'ComboBoxItems' explizit zu einer ComboBox hinzufügen und mit ihrem Event verbinden. Es klappt. –

+1

Ich verstehe. Dieser Code verhindert das Scrollen für Mausereignisse. Es wäre mehr Logik erforderlich, um das Rollen für Tastaturereignisse wie vom Benutzer erwartet zu ermöglichen, aber dieser Code beantwortet meine ursprüngliche Frage. – JoeGaggler

+1

@JoeGaggler Ich habe festgestellt, dass es auch vom 'ItemsPanel' -Ereignis funktioniert - was die Anzahl der angeschlossenen eventHandler reduziert. –

4

Von dem, was ich sagen kann scheint dies durch die Elemente an der Unterseite des Lichts verursacht werden "teilweise angezeigt", wo ein Element durch den Container abgeschnitten wird. Wenn die Maus über ein Teilelement wie dieses wobbelt, scrollt WPF das gesamte Objekt in die Ansicht, was manchmal ein anderes Teilelement an der Unterseite hinterlassen kann.

In WinForms kann dies durch Festlegen der .IntegralHeight behoben werden, aber keine solche Eigenschaft existiert in WPF von dem, was ich sagen kann. Wenn alle Elemente in Ihrer Combobox die gleiche Höhe haben, können Sie die Höhe der Liste der Combobox an ein Vielfaches der Elementhöhe binden, z. B. 10 x 20px große Elemente anzeigen und auf 200 setzen.

+0

Das ist eine großartige Theorie, aber es schien nicht zu funktionieren, als ich es ausprobierte. Ich war in der Lage, die Elementhöhe explizit mit der 'ItemTemplate' -Eigenschaft festzulegen und dann die' MaxDropDownHeight' als ein Integral der Elementhöhe festzulegen. Das Verhalten trat immer noch auf, wenn Sie die Maus auf den Rand des Dropdown-Menüs bewegen. Ich habe auch versucht, die Höhe +/- 1px zu justieren, um sicherzustellen, dass es nicht um ein eins-zu-eins-Problem ging. – JoeGaggler

0

Die ausgewählte Antwort von Andrew Hanlon vermeidet, dass die Liste beim Öffnen zum ausgewählten Element blättert. musste ich auch diese in den Event-Handler hinzufügen („Liste“ ist die 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; 
}