1

我正在尝试使用 Flip View 创建一个简单的相册(Windows Store App)。

我在 ScrollViewer 中嵌入了 Image 元素。我可以浏览照片,但我想做以下事情。

  • 图像应该均匀地填充屏幕的高度[当图像未缩放时]。我得到几个项目的垂直滚动条。当所有图像的高度相同时,我没有这个问题。
  • 当我改变屏幕的方向时,图像的一部分被剪裁在右侧。
  • 当我在页面之间移动时,滚动查看器应该忘记缩放级别(将缩放系数重置为 1)。

这是我现在拥有的代码。我究竟做错了什么?我应该在 EventHandler 中添加什么来重置 ScrollViewer 的缩放因子。

<FlipView 
    Name="MainFlipView"
    Margin="0"
    Height="{Binding ActualHeight, ElementName=pageRoot, Mode=OneWay}"
    Width="{Binding ActualWidth, ElementName=pageRoot, Mode=OneWay}"
    Background="Black">
         <FlipView.ItemTemplate>
              <DataTemplate>
                  <ScrollViewer Name="myScrollViewer" ZoomMode="Enabled"
                                Height="{Binding ActualHeight, ElementName=pageRoot, Mode=OneWay}"
                                Width="{Binding ActualWidth, ElementName=pageRoot, Mode=OneWay}"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                HorizontalScrollBarVisibility="Auto"
                                VerticalScrollBarVisibility="Auto"
                                MinZoomFactor="0.5"
                                MaxZoomFactor="2.5"
                                Margin="0" >
                       <Image Source="{Binding Path=Image}"
                              Name="MainImage" Stretch="Uniform" />
                  </ScrollViewer>
            </DataTemplate>
        </FlipView.ItemTemplate>
    </FlipView>
4

4 回答 4

4

user2199147所说的应该解决你的第一个要点,另外两个我必须以编程方式修复,但应该注意我还必须使用VisualTreeHelper你必须导入的类,以及帮助我​​使用帮助器的扩展方法班级。

首先,我必须从VisualTreeHelper扩展中找到一个方法,它可以找到任意类型的第一个元素FlipView

private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
{
    if (parentElement != null)
    {
        var count = VisualTreeHelper.GetChildrenCount(parentElement);
        if (count == 0)
            return null;

        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(parentElement, i);

            if (child != null && child is T)
                return (T)child;
            else
            {
                var result = FindFirstElementInVisualTree<T>(child);
                if (result != null)
                {
                    return result;
                }
            }
        }
    }
    return null;
}

为了进入纵向模式,我添加了一个回调处理程序,并简单地将翻转视图中的WindowSizeChanged所有 s 重置为默认值。ScrollViewer

private void WindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    //Reset scroll view size
    int count = MainFlipView.Items.Count;
    for(int i = 0; i < count; i++)
    {
        var flipViewItem = MainFlipView.ItemContainerGenerator.ContainerFromIndex((i));
        var scrollViewItem = FindFirstElementInVisualTree<ScrollViewer>(flipViewItem);
        if (scrollViewItem is ScrollViewer)
        {
            ScrollViewer scroll = (ScrollViewer)scrollViewItem;
            scroll.Height = e.Size.Height; //Reset width and height to match the new size
            scroll.Width = e.Size.Width;
            scroll.ZoomToFactor(1.0f);//Zoom to default factor
        }
    }
}

然后在您的构造函数Window.Current.SizeChanged += WindowSizeChanged;中,您需要调用回调。

现在,要将每个ScrollViewer回到其默认位置,我们做了类似的过程,只有在FlipView更改选择时,我们只能重置ScrollViewer返回其默认变焦因子

private void FlipViewSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (sender is FlipView)
    {
        FlipView item = (FlipView)sender;
        var flipViewItem = ((FlipView)sender).ItemContainerGenerator.ContainerFromIndex(((FlipView)sender).SelectedIndex);
        var scrollViewItem = FindFirstElementInVisualTree<ScrollViewer>(flipViewItem);
        if (scrollViewItem is ScrollViewer)
        {
            ScrollViewer scroll = (ScrollViewer)scrollViewItem;
            scroll.ScrollToHorizontalOffset(0);
            scroll.ScrollToVerticalOffset(0);
            scroll.ZoomToFactor(1.0f);
        }
    }
}

再一次,我们必须在构造函数中调用,看起来像MainFlipView.SelectionChanged += FlipViewSelectionChanged;

我知道这些方法看起来真的很笨拙和迂回,因为它们确实如此,但这对我有用,我希望这会有所帮助。

于 2013-06-07T03:57:55.047 回答
1

尝试将滚动查看器的高度和宽度绑定更改为图像。

<FlipView 
    Name="MainFlipView"
    Margin="0"
    Height="{Binding ActualHeight, ElementName=pageRoot, Mode=OneWay}"
    Width="{Binding ActualWidth, ElementName=pageRoot, Mode=OneWay}"
    Background="Black">
         <FlipView.ItemTemplate>
              <DataTemplate>
                  <ScrollViewer Name="myScrollViewer" ZoomMode="Enabled"

                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                HorizontalScrollBarVisibility="Auto"
                                VerticalScrollBarVisibility="Auto"
                                MinZoomFactor="0.5"
                                MaxZoomFactor="2.5"
                                Margin="0" >
                       <Image Source="{Binding Path=Image}"
                                      Height="{Binding ActualHeight, ElementName=pageRoot, Mode=OneWay}"
                                      Width="{Binding ActualWidth, ElementName=pageRoot, Mode=OneWay}"
                                      Name="MainImage" Stretch="Uniform" />
                  </ScrollViewer>
            </DataTemplate>
        </FlipView.ItemTemplate>
    </FlipView>
于 2013-03-22T12:15:47.153 回答
1

WinRT 的良好做法是:

1) 为 ScrollViewer 制作附加属性,这将改变 ZoomFactor

public class ScrollViewerExtension : DependencyObject
{
    public static readonly DependencyProperty ScrollViewerZoomFactorProperty = DependencyProperty.RegisterAttached(
        "ScrollViewerZoomFactor", typeof(double), typeof(ScrollViewerExtension), new PropertyMetadata(default(double), OnZoomFactorChanged));

    public static void SetScrollViewerZoomFactor(DependencyObject element, double value)
    {
        element.SetValue(ScrollViewerZoomFactorProperty, value);
    }

    public static double GetScrollViewerZoomFactor(DependencyObject element)
    {
        return (double)element.GetValue(ScrollViewerZoomFactorProperty);
    }

    private static void OnZoomFactorChanged(DependencyObject depObject, DependencyPropertyChangedEventArgs args)
    {
        if (depObject is ScrollViewer)
        {
            var scrollViewer = (ScrollViewer)depObject;
            var zoomValue = (double)args.NewValue;
            if (!Double.IsNaN(zoomValue))
                scrollViewer.ZoomToFactor((float)zoomValue);
        }
        else
        {
            throw new Exception("ARE YOU KIDDING ME ? ITS NOT SCROLLVIEWER");
        }
    }
}

2) 更换 FlipViewItem 模板

<Style TargetType="FlipViewItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid Width="1040">
                    <ScrollViewer HorizontalAlignment="Stretch"
                                  HorizontalScrollBarVisibility="Auto"
                                  MaxZoomFactor="4"
                                  MinZoomFactor="1"
                                  Tag="{Binding IsSelected}"
                                  VerticalScrollBarVisibility="Auto"
                                  VerticalScrollMode="Auto"
                                  ZoomMode="Enabled"
                                  extension:ScrollViewerExtension.ScrollViewerZoomFactor="{Binding  RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Converter={StaticResource IsSelectedToZoom}}">
                        <ContentPresenter />
                    </ScrollViewer>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3) 创建转换器,如果未选择项目,它将更改 ScrollViewerZoomFactor 为默认值。

public class IsSelectedToZoomConverter :DependencyObject, IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var val = (bool) value;
        return val ? Double.NaN : 1.0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

4) FlipView 代码如下所示:

<FlipView x:Name="FlipView"
          Grid.Row="5"
          Width="1040"
          MinHeight="392"
          MaxHeight="600"
          ItemsSource="{Binding Path=CurrentSession.Photos}"
          Visibility="{Binding CurrentSession.HasContent,
                               Converter={StaticResource BoolToVisibility}}">
  <FlipView.ItemContainerStyle>
    <Style TargetType="FlipViewItem">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate>
            <Grid Width="1040">
              <ScrollViewer HorizontalAlignment="Stretch"
                            HorizontalScrollBarVisibility="Auto"
                            MaxZoomFactor="4"
                            MinZoomFactor="1"
                            Tag="{Binding IsSelected}"
                            VerticalScrollBarVisibility="Auto"
                            VerticalScrollMode="Auto"
                            ZoomMode="Enabled"
                            extension:ScrollViewerExtension.ScrollViewerZoomFactor="{Binding RelativeSource={RelativeSource TemplatedParent},
                                                                                             Path=IsSelected,
                                                                                             Converter={StaticResource IsSelectedToZoom}}">
                  <ContentPresenter />
              </ScrollViewer>
            </Grid>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    </FlipView.ItemContainerStyle>
    <FlipView.ItemTemplate>
      <DataTemplate>
        <Image HorizontalAlignment="Stretch" Source="{Binding Path=Path}" />
      </DataTemplate>
    </FlipView.ItemTemplate>
</FlipView>
于 2015-09-29T19:51:01.190 回答
0

为什么你的 FlipViewItemTemplate 中有一个 ScrollViewer?Thie 模板将用于每个项目,因此对于您添加到项目列表的每个图像。也就是说,在模板中包含 Image 元素就足够了。这至少应该避免比屏幕大的图像的滚动条,因为然后 Stretch="Uniform" 应该处理调整大小......

于 2013-03-20T15:28:00.940 回答