none
FlipView 에서 화면을 수직으로 전환시 이미지를 Uniform 하게 보여주고 싶습니다 RRS feed

  • 질문

  • 안녕하세요 다람쥐이 입니다

    FlipView 로 이미지 뷰어를 만들려고 하는데 확대축소를 위해 FlipVIewDataTemplate ScrollViewer 를 사용했습니다 그런데 문제는 수직으로 방향을 전환했을 때 이미지가 Uniform 하게 나타나야하는데 두번째 스샷처럼 오른쪽이 잘려서 나옵니다

    링크된 소스를 보시고 해결 방법을 찾아 주셨으면 합니다 감사합니다. 좋은 하루 되세요~^^

    테스트 앱 링크

    https://onedrive.live.com/#cid=CAE957F2DF3FFD76&id=CAE957F2DF3FFD76%21126



    • 편집됨 Squirrel Lee 2014년 3월 18일 화요일 오전 6:17
    2014년 3월 18일 화요일 오전 6:15

답변

  • 그러면 템플릿을 사용하셨으니 이렇게 해보시죠.

    컨셉은, 이런저런 샘플들을 모아서 간단히 구성해보자면, 템플릿을 선별적으로 선택할 수 있게 하는 DataTemplateSelector와 화면의 현재 크기를 받아올 수 있는 width와 height에 대한 convertor를 구현하여 landscape와 portrait 모드에 맞는 템플릿을 먼저 만들어두고 화면의 현재 크기를 인식하여 그에 맞는 템플릿을 바인딩할 수 있도록 구현하는 것입니다.

    그냥 아이디어이므로 많이 다듬어서 적용하시면 될 것 같습니다.

    OrientationTemplateSelector.cs

    using System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Data;
    
    namespace App49
    {
        public class OrientationTemplateSelector : DataTemplateSelector
        {
            protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
            {
                var customItem = item as DataItem;
                if (customItem == null)
                    return null;
    
                string templateName = String.Empty;
                if (Window.Current.Bounds.Width > Window.Current.Bounds.Height)
                {
                    templateName = "FlipViewDataTemplate";
                }
                else
                {
                    templateName = "FlipViewDataTemplatePortrait";
                }
    
                object template = null;
                Application.Current.Resources.TryGetValue(templateName, out template);
    
                return template as DataTemplate;
            }
        }
    
        public class WidthConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return Window.Current.Bounds.Width;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    
        public class HeightConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return Window.Current.Bounds.Height;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    그리고 App.xaml에는 두 가지 유형의 템플릿을 두는 거죠.

    <Application
        x:Class="App49.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App49">
        
        <Application.Resources>
            <local:WidthConverter x:Key="wc" />
            <local:HeightConverter x:Key="hc" />
            <DataTemplate x:Key="FlipViewDataTemplate">
                <ScrollViewer x:Name="svPhotos"
            		    ZoomMode="Enabled" 
            		    HorizontalScrollMode="Auto"
            		    VerticalScrollMode="Auto"
            		    VerticalSnapPointsType="None"
            		    HorizontalSnapPointsType="None"
            		    HorizontalScrollBarVisibility="Auto"
            		    VerticalScrollBarVisibility="Auto"
            		    MinZoomFactor="1"            
            		    MaxZoomFactor="3.5" HorizontalContentAlignment="Center">
                    <Grid>
                        <Image Stretch="Uniform" Source="{Binding ImagePath}"
                            Width="{Binding ActualWidth, ElementName=page, Mode=OneWay}" Height="{Binding ActualHeight, ElementName=page, Mode=OneWay}"/>
                    </Grid>
                </ScrollViewer>
            </DataTemplate>
            <DataTemplate x:Key="FlipViewDataTemplatePortrait">
                <ScrollViewer x:Name="svPhotos"
            		    ZoomMode="Enabled" 
            		    HorizontalScrollMode="Auto"
            		    VerticalScrollMode="Auto"
            		    VerticalSnapPointsType="None"
            		    HorizontalSnapPointsType="None"
            		    HorizontalScrollBarVisibility="Auto"
            		    VerticalScrollBarVisibility="Auto"
            		    MinZoomFactor="1"            
            		    MaxZoomFactor="3.5" HorizontalContentAlignment="Center">
                    <Grid>
                        <Image Stretch="Uniform" Source="{Binding ImagePath}"
                               Width="{Binding Converter={StaticResource wc}}" Height="{Binding Converter={StaticResource hc}}"/>
                    </Grid>
                </ScrollViewer>
            </DataTemplate>
        </Application.Resources>
    
    </Application>

    MainPage.xaml 파일에는 App.xaml에 정의한 템플릿을 현재 화면의 orientation에 따라 선택할 수 있도록 로컬 리소스에 OrientationTemplateSelector를 두고 filpView에 그것을 연동하는 것입니다.

    <Page x:Name="page"
        x:Class="App49.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App49"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <local:OrientationTemplateSelector x:Key="OrientationTemplateSelector" />
        </Page.Resources>
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <FlipView x:Name="flipView" ItemTemplateSelector="{StaticResource OrientationTemplateSelector}" ItemsSource="{Binding}"/>
        </Grid>
    </Page>
    

    • 답변으로 표시됨 Squirrel Lee 2014년 3월 19일 수요일 오전 7:34
    2014년 3월 19일 수요일 오전 12:40

모든 응답

  • 제가 다른 업무가 많아서 아직 소스는 보지 못했습니다만,

    화면이 Portrait 모드로 돌아갔을 때 어떻게 렌더링할지가 결정되어있어야 합니다.

    위 화면을 봐서는 Landscape 모드일 때의 저 그림을 Portrait 모드에서 어떻게 화면에 채워넣으시겠다는 것인지 잘 모르겠습니다.

    2014년 3월 18일 화요일 오전 6:43
  • Portrait 모드일 때 다음과 같이 좌우가 Uniform 하게 꽉차게 하고 싶습니다

    죄송한데 시간 되실 때 잠시 코드를 봐주시면 안될까요? ^^

    좋은 하루 되세요~ 

    2014년 3월 18일 화요일 오전 6:56
  • 코드를 봤는데, 이게 실제 개발 코드인지는 모르겠습니다만 위 질문의 요구사항 뿐 아니라 앱의 여러 뷰 모드에 대응할 수 있는 준비가 안 되어있는 것으로 보입니다. 저렇게 바뀌는 것이 XAML 엘리먼트의 속성 하나 바꿔서 되는 게 아닙니다. 이번에는 제가 대강 샘플 코드를 드리면 저렇게 동작하도록 만들어 드릴 수는 있겠지만 snap view 같은 뷰 모드에 대한 요구 사항 등을 맞추다보면 지금 만드신 구조로는 개발이 점점 어려워지지 않을까 싶습니다.
    2014년 3월 18일 화요일 오후 12:45
  • 답변 감사드립니다 ^^

    실제 개발 코드는 아니고 질문과 관련된 부분만 재구성한 코드입니다

    제가 구현하고자하는 것은 일종의 포토 뷰어 기능인데

    FlipView 컨트롤을 사용해서 이미지를 보여주고 이미지를 확대, 축소 할 수있게 구현하려고 합니다

    첨부한 코드로는 위의 기능이 모두 가능한데 한 가지 문제가

    Portrait 로 뷰가 변경될 때 이미지를 위의 스크린샷처럼 Uniform 하게 보여주는게 안되고 오른쪽이 잘려서 나옵니다

    Snap View 같은 뷰 모드에 대한 구현은 개발 코드에는 구현이 되어있는데 질문을 위한 참고용으로 FlipView 관련 부분만 재구성하다보니 코드가 좀 엉성해 진것 같습니다

    혹시 제가 구현하고자 하는 기능을 가지는 참고할 만한 소스가 없을까요?

    답변 부탁드립니다. 

    지속적으로 관심가져 주시고 많은 도움 주셔서 큰힘이 되고 있습니다

    진심으로 감사드립니다 좋은 하루 되세요~^^


    2014년 3월 18일 화요일 오후 3:02
  • 그러면 템플릿을 사용하셨으니 이렇게 해보시죠.

    컨셉은, 이런저런 샘플들을 모아서 간단히 구성해보자면, 템플릿을 선별적으로 선택할 수 있게 하는 DataTemplateSelector와 화면의 현재 크기를 받아올 수 있는 width와 height에 대한 convertor를 구현하여 landscape와 portrait 모드에 맞는 템플릿을 먼저 만들어두고 화면의 현재 크기를 인식하여 그에 맞는 템플릿을 바인딩할 수 있도록 구현하는 것입니다.

    그냥 아이디어이므로 많이 다듬어서 적용하시면 될 것 같습니다.

    OrientationTemplateSelector.cs

    using System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Data;
    
    namespace App49
    {
        public class OrientationTemplateSelector : DataTemplateSelector
        {
            protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
            {
                var customItem = item as DataItem;
                if (customItem == null)
                    return null;
    
                string templateName = String.Empty;
                if (Window.Current.Bounds.Width > Window.Current.Bounds.Height)
                {
                    templateName = "FlipViewDataTemplate";
                }
                else
                {
                    templateName = "FlipViewDataTemplatePortrait";
                }
    
                object template = null;
                Application.Current.Resources.TryGetValue(templateName, out template);
    
                return template as DataTemplate;
            }
        }
    
        public class WidthConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return Window.Current.Bounds.Width;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    
        public class HeightConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                return Window.Current.Bounds.Height;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    그리고 App.xaml에는 두 가지 유형의 템플릿을 두는 거죠.

    <Application
        x:Class="App49.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App49">
        
        <Application.Resources>
            <local:WidthConverter x:Key="wc" />
            <local:HeightConverter x:Key="hc" />
            <DataTemplate x:Key="FlipViewDataTemplate">
                <ScrollViewer x:Name="svPhotos"
            		    ZoomMode="Enabled" 
            		    HorizontalScrollMode="Auto"
            		    VerticalScrollMode="Auto"
            		    VerticalSnapPointsType="None"
            		    HorizontalSnapPointsType="None"
            		    HorizontalScrollBarVisibility="Auto"
            		    VerticalScrollBarVisibility="Auto"
            		    MinZoomFactor="1"            
            		    MaxZoomFactor="3.5" HorizontalContentAlignment="Center">
                    <Grid>
                        <Image Stretch="Uniform" Source="{Binding ImagePath}"
                            Width="{Binding ActualWidth, ElementName=page, Mode=OneWay}" Height="{Binding ActualHeight, ElementName=page, Mode=OneWay}"/>
                    </Grid>
                </ScrollViewer>
            </DataTemplate>
            <DataTemplate x:Key="FlipViewDataTemplatePortrait">
                <ScrollViewer x:Name="svPhotos"
            		    ZoomMode="Enabled" 
            		    HorizontalScrollMode="Auto"
            		    VerticalScrollMode="Auto"
            		    VerticalSnapPointsType="None"
            		    HorizontalSnapPointsType="None"
            		    HorizontalScrollBarVisibility="Auto"
            		    VerticalScrollBarVisibility="Auto"
            		    MinZoomFactor="1"            
            		    MaxZoomFactor="3.5" HorizontalContentAlignment="Center">
                    <Grid>
                        <Image Stretch="Uniform" Source="{Binding ImagePath}"
                               Width="{Binding Converter={StaticResource wc}}" Height="{Binding Converter={StaticResource hc}}"/>
                    </Grid>
                </ScrollViewer>
            </DataTemplate>
        </Application.Resources>
    
    </Application>

    MainPage.xaml 파일에는 App.xaml에 정의한 템플릿을 현재 화면의 orientation에 따라 선택할 수 있도록 로컬 리소스에 OrientationTemplateSelector를 두고 filpView에 그것을 연동하는 것입니다.

    <Page x:Name="page"
        x:Class="App49.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App49"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <local:OrientationTemplateSelector x:Key="OrientationTemplateSelector" />
        </Page.Resources>
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <FlipView x:Name="flipView" ItemTemplateSelector="{StaticResource OrientationTemplateSelector}" ItemsSource="{Binding}"/>
        </Grid>
    </Page>
    

    • 답변으로 표시됨 Squirrel Lee 2014년 3월 19일 수요일 오전 7:34
    2014년 3월 19일 수요일 오전 12:40
  • 좋은 아이디어 인데요 ^^

    지금 적용해보고 있는데 앱실행시 Landscape 나 Portrait 상태에서는 DataTemplateSelector 에 의해서

    정삭 작동되는데 

    앱 실행 후 Landscape 에서 Portrait 상태로 화면뷰가 전환될 때 DataTemplateSelector 클래스의

    SelectTemplateCore 메서드가 실행이 되지 않아서 Portrait 상태의 Template 이 적용이 안됩니다 

    C# 코드에서 화면뷰가 전환될 때 SelectTemplateCore 메서드가 실행되도록 해야할 것 같은데 

    혹시 아신다면 답변 부탁드립니다.

    참고로 예전에 WPF 에서는 ListBox 의 컨트롤의 경우 list.Items.Refresh()

    라는 메서드가 있어서 C# 코드에서 템플릿을 다시 적용하게 할 수 있었던 걸로 기억하는데

    FlipView 에는 동일한 메서드가 없네요

    저도 그전에 여러가지로 시도해 보겠습니다 ^^

    바쁘신데 자꾸 번거롭게 해서 죄송하고 상세한 답변 주셔서 감사합니다 ^^


    • 편집됨 Squirrel Lee 2014년 3월 19일 수요일 오전 2:00
    2014년 3월 19일 수요일 오전 1:46