Margin auf ItemsControl der Virtualisierung ListBox funktioniert nicht richtig

8

Ich habe ein Problem mit einer Klasse, die ListBox in Windows Phone 7 Silverlight erweitert. Die Idee ist, eine vollständige ScrollViewer (schwarz, z. B. füllt den gesamten Handy-Bildschirm) und dass die ItemsPresenter (rot) hat eine Marge (grün). Dies wird verwendet, um einen Rand um die gesamte Liste zu haben, aber die Bildlaufleisten beginnen am oberen rechten Rand und enden am unteren rechten Rand des dunklen Rechtecks:

Das Problem ist, dass ScrollViewer nicht bis zum Ende scrollen kann, es schneidet 50 Pixel vom letzten Element in der Liste ab. Wenn ich StackPanel anstelle von VirtualizingStackPanel verwende, sind die Ränder korrekt, ABER die Liste wird nicht mehr virtualisiert.

Danke für irgendwelche Ideen, ich habe viel versucht, aber nichts funktioniert. Ist das ein Kontrollfehler?

LÖSUNG: Verwenden Sie die Eigenschaft InnerMargin des Steuerelements ExtendedListBox aus der MyToolkit -Bibliothek!

C #:

%Vor%

XAML (z. B. App.xaml):

%Vor%

Update 1

Ich habe eine einfache Beispiel-App erstellt: Die Bildlaufleiste kann am Ende nicht scrollen ... Wenn Sie VirtualizingStackPanel in StackPanel in App.xaml ändern und es wie erwartet funktioniert, aber ohne Virtualisierung

SampleApp.zip

Update 2 Einige Beispielbilder hinzugefügt. Bildlaufleisten sind blau, um ihre Position anzuzeigen.

Erwartete Ergebnisse (verwenden Sie StackPanel anstelle von VirtualizingStackPanel ):

Korrigieren_01: Bildlaufleiste oben

Korrigieren_01: Bildlaufleiste in der Mitte

Korrigieren_01: Bildlaufleiste unten

Falsche Beispiele:

Falsch_01: Rand immer sichtbar (Beispiel: Bildlaufposition Mitte)

Einzige Lösung ist das Hinzufügen eines Dummy-Elements am Ende der Liste, um den Rand zu kompensieren. Ich werde versuchen, dieses Dummy-Element dynamisch in der Steuerlogik hinzuzufügen ... Füg etwas Logik in das gebundene ObservableCollection hinzu oder das Ansichtsmodell ist keine Option.

UPDATE: Ich habe meine endgültige Lösung als separate Antwort hinzugefügt. Überprüfen Sie die Klasse ExtendedListBox .

    
Rico Suter 23.03.2014, 10:23
quelle

4 Antworten

2

Meine aktuelle Lösung: Ändere immer den Rand des letzten Elements der Liste ...

%Vor%

Mit diesem "Hack" ändere ich den Rand des letzten Listeneintrags im laufenden Betrieb (keine Notwendigkeit, etwas zur gebundenen Liste hinzuzufügen). Ich habe dieses letzte Steuerelement entwickelt:

(Das Listenfeld hat ein neues Ereignis für PrepareContainerForItem , eine Eigenschaft und ein Ereignis für IsScrolling (es gibt auch eine erweiterte Eigenschaft LowProfileImageLoader mit IsSuspended , die im IsScrolling Ereignis zur Verbesserung gesetzt werden kann) Scrollglätte ...) und die neue Eigenschaft InnerMargin für das beschriebene Problem ...

Update: Überprüfen Sie die ExtendedListBox Klasse meiner MyToolkit-Bibliothek, die die Lösung bietet hier beschrieben ...

    
Rico Suter 11.11.2011, 09:52
quelle
1

Ich denke, was wäre ein einfacherer Weg, anstatt sich mit Stilen zu beschäftigen, ist -

Erstens brauchen Sie keine oberen und unteren Ränder, da Sie sowieso keine horizontalen Bildlaufleisten haben sollten. Sie können diese beiden Ränder direkt zu Ihrer Listbox hinzufügen.

%Vor%

Um zwischen den Listbox-Elementen und der Bildlaufleiste eine kleine Lücke (d. h. den linken und den rechten Rand) zu erhalten, müssen Sie in Ihrem ItemContainerStyle nur einen linken und rechten Rand von 50 festlegen.

%Vor%

UPDATE (Leistungseinfluss!)

Okay, behalten Sie Ihren gesamten vorhandenen Code bei und fügen Sie diese Zeile dann zu ScrollViewer in Ihrem benutzerdefinierten Listenfeldstil hinzu.

%Vor%

Es scheint so zu sein, dass ManipulationMode="Control" (Standard ist "System") Ihr Problem behoben hat, dies könnte jedoch zu einer schlechteren Leistung von ScrollViewer führen. Bitte werfen Sie einen Blick auf dieser Post . Ich denke, es ist ein Fehler.

Laden Sie viele Daten in diese Listbox? Sie müssen wirklich die Leistung auf einem tatsächlichen Telefon prüfen. Wenn das Scrollen glatt ist, denke ich, es könnte ein Weg sein, wenn nicht, lass es mich wissen, ich werde versuchen, an etwas anderes zu denken ...

    
Justin XL 09.11.2011 22:57
quelle
0

Was ich normalerweise mache, wenn ich in einer ListBox padding haben möchte, so kann ich zum Beispiel den gesamten Bildschirm sogar den Teil unter einer transparenten ApplicationBar belegen, aber trotzdem auf das letzte Element in der ListBox-I zugreifen können Verwenden Sie einen DataTemplateSelector ( Ссылка ) und definieren Sie eine (oder mehrere) Vorlagen für reguläre Elemente und auch eine Vorlage für ein PaddingViewModel, das eine bestimmte Höhe definiert. Dann - ich stelle sicher, dass meine ItemsSource eine Sammlung ist, die dieses PaddingViewModel als letztes Element hat. Dann fügt meine Auffüllung DataTemplate die Auffüllung am Ende der Liste hinzu und ich kann auch ListBox-Elemente mit verschiedenen Vorlagen haben.

%Vor%

Eine weitere Sache, die Sie beachten sollten - es gibt einige Fehler in der ListBox / VirtualizingStackPanel, dass, wenn Ihre Elemente nicht von gleichbleibender Höhe sind - Sie manchmal die unteren Elemente in der ListBox nicht sehen und nach oben und unten scrollen müssen, um zu beheben es. ( Ссылка )

    
Filip Skakun 09.11.2011 23:48
quelle
-2

Das Setzen von Margen auf ItemsPresenter (oder ein Kind eines ScrollViewer ) unterbricht die interne Logik von ScrollViewer . Versuchen Sie, den gleichen Wert wie "Padding" für ScrollViewer festzulegen, also:

%Vor%

Update: (nach dem Betrachten des angehängten Projekts)

In der ScrollViewer-Vorlage. Die Bindung für die Padding-Eigenschaft wurde im Hauptraster des Steuerelements und nicht in ScrollContentPresenter festgelegt, wie es in WPF \ silverlight geschieht. Dadurch wurde die Position der Bildlaufleiste beeinflusst, indem die padding-Eigenschaft festgelegt wurde. Beim ScrollViewer entspricht die Einstellung "Padding" der Einstellung von "Margin". (Microsoft, warum Vorlagen für das Schlimmste ändern !? War es absichtlich?).

Fügen Sie diesen Stil vor hinzu, um den Stil des Listenfelds in App.xaml:

zu ändern %Vor%

Fügen Sie dem Stil des Listenfelds einige Änderungen hinzu:

  1. Hinzufügen von Setter für Padding im Listenfeld: <Setter Property="Padding" Value="30,50" />
  2. Fügen Sie dem Scroll-Viewer in der Vorlage Padding="{TemplateBinding Padding}" und Style="{StaticResource ScrollViewerStyle1}" .
  3. hinzu
  4. Entfernen Sie die Margin-Zuweisung für ItemsPresenter .

Dies führt zu einem weiteren fehlerhaften Verhalten: Die Bildlaufleiste scrollt nicht bis zum unteren Bildschirmrand. Kein großes Problem im Vergleich zum letzten Punkt, aber nervig.

    
XAMeLi 06.11.2011 21:23
quelle