5

Ich habe eine Windows 8 Store App mit C#/XAML erstellt. Meine Oberfläche enthält eine scrollbare Liste, die mit einem ScrollViewer gerendert wird. Ich möchte Manipulationsereignisse auf den Elementen innerhalb der Liste behandeln können, aber die Einstellung auf etwas anderes als None auf dem Listenelement bewirkt, dass meine Liste nicht mehr scrollt.ScrollViewer und Umgang mit Manipulationsereignissen auf untergeordneten Elementen

Hier ist eine vereinfachte Version der Benutzeroberfläche:

<ScrollViewer> 
    <Border/> <!-- these contain child content --> 
    <Border/> 
    <Border/> 
    <!-- Set ManipulationMode on an element in order to receive manipulation events --> 
    <!-- This causes the scroll viewer to stop working! --> 
    <Border ManipulationMode="All" 
      ManipulationDelta="..."/> 
    <Border/> 
    <Border/> 
</ScrollViewer> 

Ich verstehe, dass der WinRT ScrollViewer eine spezielles ManipulationMode von System aus Leistungsgründen verwendet, aber ich würde eine vertikal scrollen Liste haben mag, Elemente enthält, reagieren auf horizontale Manipulation/Gesten. Kann jemand an einen kreativen Workaround denken, der dies ermöglicht?

Antwort

8

Ich habe ein transparentes Rechteck auf den ScrollViewer gelegt und manipuliere dort. Wenn ich finde, dass die Manipulation den ScrollViewer scrollen sollte, scrolle ich den ScrollViewer mit den ScrollToHorizontal/VerticalOffset() Methoden. Auf ManipulationStarted benutze ich auch VisualTreeHelper.FindElementsInHostCoordinates, um zu überprüfen, welches Element ich auch manipulieren kann und dann kann ich entscheiden, ob ich dieses Element manipuliere oder nicht, abhängig von verschiedenen Bedingungen. Es ist jedoch ziemlich viel benutzerdefinierter Code. Sie müssen auch die RenderTransform des ScrollContentPresenter im ScrollViewer aktualisieren, wenn der Benutzer versucht, mehr als den minimalen/maximalen Offset zu ziehen, um das ScrollViewer-Standardverhalten nachzuahmen, das Mausrad zu bedienen usw. Nichts, womit Sie nicht umgehen könnten. Ich konnte leider keinen besseren Weg finden und bin interessiert, wenn jemand einen findet.

EDIT * Eine andere Lösung, an die ich dachte, als ich versuchte, another similar question zu beantworten, war, einen anderen ScrollViewer als untergeordnetes Element zu verwenden und seine ViewChanged-Ereignisse anstelle von Manipulationsereignissen zu verwenden.

EDIT 2 *

auch unter Windows 8.1 Sie erhalten ManipulationModes.System, die mit anderen Modi kombiniert sollten Sie innerhalb eines ScrollViewer Manipulationen zu handhaben lassen. Dann können Sie CancelDirectManipulations() auf dem manipulierten Element aufrufen, wenn Sie möchten, dass das übergeordnete Element ScrollViewers die Bearbeitung von Manipulationen für den Zoombereich & stoppt.

+0

Wow - das ist eine Menge Arbeit. Sie kümmern sich also im Prinzip selbst um den ScrollViewer? Bedeutet das, dass Sie auch eigene Trägheitsberechnungen durchführen müssen, damit es natürlich scrollt? Oder macht es das automatisch, wenn Sie den vertikalen Offset ändern? – ColinE

+1

Manipulationen in Jupiter haben eingebaute Trägheit standardmäßig aktiviert, so dass Sie das abdecken. Sie müssen nur sicherstellen, dass Sie den ScrollContentPresenter nicht am Ende der Liste zerquetschen, wenn das Scrollen aufgrund von Trägheit geschieht. Die Manipulationen sind normalerweise ziemlich flüssig, aber Sie könnten wahrscheinlich ScrollViewer-Animationen wie die aus dem [WinRT XAML Toolkit] (http://bit.ly/WinRTXamlToolkit) verwenden, um das Scrollen bei Verwendung des Scrollrads zu glätten. Übrigens, ich habe vergessen zu erwähnen, dass Sie vielleicht auch den Fokus auf Elemente einstellen möchten, wenn Sie auf das Overlay tippen ... :) –

+1

@Coline Prüfe meine Antwort auf [diese Frage] (http: // stackoverflow.com/questions/14153038/how-to-allow-Manipulationen-in-listview-gridview-item-Steuerelemente-While-Erlauben/14161596 # 14161596) für eine andere Lösung. –

10

es kann lange dauern, aber keine gute Lösung gefunden. Ich habe gerade erreicht, was ich wollte.

public MovableGrid() 
     { 
      ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.System; 
      AddHandler(ManipulationDeltaEvent, new ManipulationDeltaEventHandler(UIElement_OnManipulationDelta), true); 
      AddHandler(ManipulationCompletedEvent, new ManipulationCompletedEventHandler(UIElement_OnManipulationCompleted), true); 
     } 

wollte ich meine MovableGrid auf der X-Achse bewegt zu werden, und ich habe die Liste von MovableGrids, die ich mit Scroll gescrollt werden wollte. Das reicht, um das zu tun.

+0

Vielen Dank! Genau das habe ich gebraucht! – Pam

Verwandte Themen