我有windows phone 10(C#UWP)应用程序,我在listview中使用scrollviewer来显示图像的幻灯片。在滚动查看器的视图更改事件上,我检查哪个图像容器对于用户更加可见,并使用ChangeView方法将该图像移动到显示器上看到的唯一图像。这一切都运行良好,但如果我在ChangeView处于活动状态时按住触摸屏,图像会调整大小并且我收到错误“此对象已被密封,因此不再允许此更改”,这是我无法捕获的。
XAML: (注意,CurrentSizeConverter只根据参数提供可见的页面边界)
<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> .........
私人变量:
private static bool _imagesShowing = false;
private ScrollViewer _imagesViewer;
事件处理:
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);
}
}
最后,将任何可观察的集合列表与xaml绑定属性绑定,其中ImageSource属性是图像StorageFile(在我的例子中,它们都是.jpg)列表视图。
基本上当smoothScrolling为true时,滚动正在进行中,我点击并按住项目,项目调整大小,我可以在按住时移动它们,当我放开应用程序从上方处理未处理的异常时。
有什么想法吗?
答案 0 :(得分:2)
您可能会干扰DirectManipulation,因此滚动时会出现异常。
发生的事情是,只要有“导致FlipView动画的触摸事件”,导致该动画的内容就是内置于FlipView中的ScrollViewer,用于翻转。滚动查看器取消指针输入,直到平移完成并且无法取回。这是一个名为DirectManipulation的功能,它现在在单独的线程上处理输入,以提供最平滑的平移处理。 (指针事件在UI线程中触发) 在http://social.msdn.microsoft.com/Forums/windowsapps/en-US/1e6732d3-0457-4ddc-b762-963ab974491c/pointerreleased-and-flipview
此处遇到同样的问题:Why ScrollViewer fired PointerCaptureLost when starting scroll?