2016-12-07 11 views
1

私はWindows Phone 10(C#UWP)アプリケーションを持っており、リストビューでscrollviewerを使用して画像のスライドを表示しています。スクロールビューアのビュー変更されたイベントでは、どのイメージコンテナがユーザーにとってより見えているかチェックし、ChangeViewメソッドを使用してそのイメージを表示された唯一のイメージに移動します。これはうまくいきますが、ChangeViewがアクティブな状態でタッチスクリーンを押し続けると、画像のサイズが変更され、「このオブジェクトは封印されているため、この変更は許可されなくなりました」というエラーが表示されます。ScrollViewer.ChangeViewがアクティブな状態で画面にタッチするUWP

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プロパティはImage StorageFileです(私の場合はすべて.jpgです)。

スムーススクロールがtrueの場合、スクロールが進行中です。項目をタップして保持するとアイテムがサイズ変更され、保持しながら移動できます。

アイデア?

+0

はあなたの問題を再現するには何の十分なコードがありません。再現されたプロジェクトを提供するには、[ask]を参考にしてください。少なくともScrollToElementメソッドの呼び出し場所と方法 –

+0

ヒントをお寄せいただきありがとうございます。コードスニペットが更新されました。すべてが再現可能になりました。したがって、スクロールして放すと、ScrollToElementが呼び出され、scrollviewが自動的にスクロールして、ユーザーが見やすいイメージになります。この自動スクロールが行われている間、画面をタップして上下にスワイプすると問題が発生します。 – user2081328

答えて

1

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?

+0

私はスクロール中に例外がありません。 FlipViewを使用していません。私はプログラムで、リストビューに組み込まれたScrollViewerのアニメーションを開始しています。アニメーションが進行中のときに、上下左右に動かすと例外が発生します。 – user2081328

+0

はい、私が与えた例はFlipViewですが、内部的にはあなたのケースと同じScrollViewerです。ポイントは、ScrollViewerは、ハードウェアアクセラレーションされた排他的なパイプラインである直接操作を使用することです。パイプラインに関わるデータを扱うとすぐに、例外が発生します。 – MoDu

+1

これは、問題の原因と見た目をよりよく理解することができます。あなたはいくつかの回避策(ScrollViewがポインタを保持している間にListViewをタップすることを許可しないようにしてください)の良いアイデアはありますか? – user2081328

関連する問題