Ich habe Windows Phone 10 (C# UWP) App und ich benutze ScrollViewer in ListView, um Folie von Bildern anzuzeigen. Beim geänderten Ereignis für scrollviewer überprüfe ich, welcher Bildcontainer für den Benutzer besser sichtbar ist und verwende die ChangeView-Methode, um das Bild als einziges auf dem Bildschirm angezeigt zu bekommen. Das alles funktioniert gut, aber wenn ich den Touchscreen drücke und halte, während ChangeView aktiv ist, ändern sich die Bilder und ich bekomme eine Fehlermeldung "Dieses Objekt wurde versiegelt, so dass diese Änderung nicht länger erlaubt ist", die ich nicht erfassen kann.Berühren Sie auf dem Bildschirm, während ScrollViewer.ChangeView aktiv ist bricht App UWP
XAML: (Hinweis, CurrentSizeConverter gibt nur sichtbare Seite Grenzen basierend auf Parameter)
<Page.Resources>
<DataTemplate x:Key="dtPhotoView">
<Grid x:Name="grPhotoView" Width="{Binding Id, Converter={StaticResource CurrentSizeConverter}, ConverterParameter=Width}" Height="{Binding Id, Converter={StaticResource CurrentSizeConverter}, ConverterParameter=Height}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Image x:Name="imgFullSize" Source="{Binding ImageSource}" Stretch="Fill" Grid.RowSpan="2"/>
<Grid Grid.Row="1" x:Name="grDeleteFullImage" Background="#66000000">
<Button x:Name="btnDeletePhoto" Style="{StaticResource btnActionCommandButtonStyle}" Tag="{Binding Id}" Canvas.ZIndex="10" Margin="0" Click="btnDeletePhoto_Click" Background="#66000000" Padding="10">
<Button.Foreground>
<ImageBrush Stretch="Uniform" ImageSource="Assets/delete_icon.png"/>
</Button.Foreground>
</Button>
</Grid>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<ListView HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="Collapsed" SelectionMode="None" IsItemClickEnabled="False" x:Name="lvPhotoView" Grid.Row="0" DataContext="{Binding}" Background="Transparent" BorderThickness="0" ItemTemplate="{StaticResource dtPhotoView}" ScrollViewer.ZoomMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.VerticalScrollMode="Disabled" PointerEntered="lvPhotoView_PointerEntered">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="2" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView> .........
privaten Variablen:
private static bool _imagesShowing = false;
private ScrollViewer _imagesViewer;
Ereignisbehandlung:
private void lvPhotoView_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
try
{
if (!_imagesShowing)
{
_imagesShowing = true;
if (_imagesViewer == null)
{
_imagesViewer = GetScrollViewer(lvPhotoView);
}
if (_imagesViewer != null)
{
_imagesViewer.ViewChanged += ImagesScrollViewer_OnViewChanged;
}
}
}
catch (Exception ex)
{
return;
}
}
public static ScrollViewer GetScrollViewer(DependencyObject depObj)
{
try
{
if (depObj is ScrollViewer)
{
return depObj as ScrollViewer;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = GetScrollViewer(child);
if (result != null)
{
return result;
}
}
return null;
}
catch
{
return null;
}
}
private async void ImagesScrollViewer_OnViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (!e.IsIntermediate)
{
var isDone = false;
try
{
_imagesViewer.ViewChanged -= ImagesScrollViewer_OnViewChanged;
_imagesViewer.HorizontalScrollMode = ScrollMode.Disabled;
_imagesViewer.IsScrollInertiaEnabled = false;
for (var i = 0; i < lvPhotoView.Items.Count; i++)
{
var item = lvPhotoView.Items[i];
var itemContainer = lvPhotoView.ContainerFromItem(item) as ListViewItem;
double firstVisValue;
var isVisible = itemContainer.IsVisibileToUserHorizontal(sender as ScrollViewer, out firstVisValue);
if (isVisible && lvPhotoView.Items.Count - 1 > i)
{
var nextItem = lvPhotoView.Items[i + 1];
var secondItemContainer = lvPhotoView.ContainerFromItem(nextItem) as ListViewItem;
double secondVisValue;
var isNextVisible = secondItemContainer.IsVisibileToUserHorizontal(sender as ScrollViewer, out secondVisValue);
if (isNextVisible)
{
_imagesViewer.ScrollToElement(firstVisValue < secondVisValue ? secondItemContainer : itemContainer);
}
await Task.Delay(800);
_imagesViewer.HorizontalScrollMode = ScrollMode.Enabled;
_imagesViewer.IsScrollInertiaEnabled = true;
_imagesShowing = false;
isDone = true;
}
}
}
finally
{
if (!isDone)
{
await Task.Delay(500);
_imagesViewer.HorizontalScrollMode = ScrollMode.Auto;
_imagesViewer.IsScrollInertiaEnabled = true;
_imagesShowing = false;
}
}
}
}
public static bool IsVisibileToUserHorizontal(this FrameworkElement element, FrameworkElement container, out double visValue)
{
visValue = 0;
if (element == null || container == null)
{
return false;
}
if (element.Visibility != Visibility.Visible)
{
return false;
}
var elementBounds = element.TransformToVisual(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
var containerBounds = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
if (elementBounds.Left >= containerBounds.Left && elementBounds.Left < containerBounds.Right)
{
visValue = containerBounds.Right - elementBounds.Left;
return true;
}
if (elementBounds.Right >= containerBounds.Left && elementBounds.Right < containerBounds.Right)
{
visValue = elementBounds.Right - containerBounds.Left;
return true;
}
return false;
}
public static void ScrollToElement(this ScrollViewer scrollViewer, UIElement element, bool isHorizontalScrolling = true, bool smoothScrolling = true, float? zoomFactor = null)
{
var transform = element.TransformToVisual((UIElement)scrollViewer.Content);
var position = transform.TransformPoint(new Point(0, 0));
if (isHorizontalScrolling)
{
scrollViewer.ChangeView(position.X, null, zoomFactor, !smoothScrolling);
}
else
{
scrollViewer.ChangeView(null, position.Y, zoomFactor, !smoothScrolling);
}
}
Schließlich binden jede beobachtbare Auflistungsliste mit XAML-Bindungseigenschaften wo ImageSource-Eigenschaft ist Image StorageFile (in meinem Fall sind sie alle .jpg) zu Listenansicht.
Im Wesentlichen wenn SmoothScrolling ist wahr, Scrolling ist im Gange und ich tippe und halte Element, Gegenstände Größe ändern und ich kann sie bewegen, während halten, und wenn ich loslassen App Bremsen mit unbehandelten Ausnahme von oben.
Irgendwelche Ideen?
Es gibt keinen genug Code Ihr Problem zu reproduzieren. Bitte verweisen Sie [fragen], um ein reproduziertes Projekt zur Verfügung zu stellen. Zumindest wo und wie Sie die 'ScrollToElement' Methode aufrufen. –
Danke für den Tipp, ich habe Code-Snippets aktualisiert, jetzt sollte alles reproduzierbar sein. Wenn Sie blättern und loslassen, wird ScrollToElement aufgerufen, und scrollview scrollt automatisch zu einem Bild, das für den Benutzer besser sichtbar ist. Während dieses automatische Scrollen geht, tippen Sie auf den Bildschirm und wischen Sie nach oben/unten und das Problem wird auftreten. – user2081328