첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
0.01MB

▶ AnimationScrollViewer.cs

using System.Windows;
using System.Windows.Controls;

namespace TestProject
{
    /// <summary>
    /// 애니메이션 스크롤 뷰어
    /// </summary>
    public class AnimationScrollViewer : ScrollViewer
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 현재 수평 오프셋 속성 - CurrentHorizontalOffsetProperty

        /// <summary>
        /// 현재 수평 오프셋 속성
        /// </summary>
        public static DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register
        (
            "CurrentHorizontalOffsetOffset",
            typeof(double),
            typeof(AnimationScrollViewer),
            new PropertyMetadata(new PropertyChangedCallback(CurrentHorizontalOffsetPropertyChangedCallback))
        );

        #endregion
        #region 현재 수직 오프셋 속성 - CurrentVerticalOffsetProperty

        /// <summary>
        /// 현재 수직 오프셋 속성
        /// </summary>
        public static DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register
        (
            "CurrentVerticalOffset",
            typeof(double),
            typeof(AnimationScrollViewer),
            new PropertyMetadata(new PropertyChangedCallback(CurrentVerticalOffsetPropertyChangedCallBack))
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 현재 수평 오프셋 - CurrentHorizontalOffset

        /// <summary>
        /// 현재 수평 오프셋
        /// </summary>
        public double CurrentHorizontalOffset
        {
            get
            {
                return (double)GetValue(CurrentHorizontalOffsetProperty);
            }
            set
            {
                SetValue(CurrentHorizontalOffsetProperty, value);
            }
        }

        #endregion
        #region 현재 수직 오프셋 - CurrentVerticalOffset

        /// <summary>
        /// 현재 수직 오프셋
        /// </summary>
        public double CurrentVerticalOffset
        {
            get
            {
                return (double)GetValue(CurrentVerticalOffsetProperty);
            }
            set
            {
                SetValue(CurrentVerticalOffsetProperty, value);
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 현재 수평 오프셋 속성 변경시 콜백 처리하기 - CurrentHorizontalOffsetPropertyChangedCallback(d, e)

        /// <summary>
        /// 현재 수평 오프셋 속성 변경시 콜백 처리하기
        /// </summary>
        /// <param name="d">의존 객체</param>
        /// <param name="e">이벤트 인자</param>
        private static void CurrentHorizontalOffsetPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            AnimationScrollViewer viewer = d as AnimationScrollViewer;

            viewer.ScrollToHorizontalOffset((double)e.NewValue);
        }

        #endregion
        #region 현재 수직 오프셋 속성 변경시 콜백 처리하기 - CurrentVerticalOffsetPropertyChangedCallBack(d, e)

        /// <summary>
        /// 현재 수직 오프셋 속성 변경시 콜백 처리하기
        /// </summary>
        /// <param name="d">의존 객체</param>
        /// <param name="e">이벤트 인자</param>
        private static void CurrentVerticalOffsetPropertyChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            AnimationScrollViewer viewer = d as AnimationScrollViewer;

            viewer.ScrollToVerticalOffset((double)e.NewValue);
        }

        #endregion
    }
}

 

728x90

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestProject"
    Width="800"
    Height="600"
    Title="ScrollViewer 클래스 : 애니메이션 스크롤 뷰어 사용하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"    />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <local:AnimationScrollViewer x:Name="animationScrollViewer" Grid.Row="0"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch">
            <StackPanel Name="contentStackPanel" />
        </local:AnimationScrollViewer>
        <StackPanel Grid.Row="1"
            Margin="0 10 0 0"
            HorizontalAlignment="Right"
            Orientation="Horizontal">
            <ComboBox Name="targetComboBox"
                VerticalAlignment="Center"
                Width="150"
                Height="25" />
            <Button Name="animateButton"
                Margin="10 0 0 0"
                VerticalAlignment="Center"
                Width="150"
                Height="30"
                Content="애니메이션 시작" />
        </StackPanel>
    </Grid>
</Window>

 

300x250

 

▶ MainWindow.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 항목 카운트
        /// </summary>
        private const int ITEM_COUNT = 50;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            for(int i = 0; i < ITEM_COUNT; i++)
            {
                Button button = CreateButton(i);

                ListViewItem item = new ListViewItem();

                item.Tag     = button;
                item.Content = "버튼 " + i.ToString();

                this.targetComboBox.Items.Add(item);

                this.contentStackPanel.Children.Add(button);

                this.animateButton.Click += animateButton_Click;
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 애니메이션 시작 버튼 클릭시 처리하기 - animateButton_Click(sender, e)

        /// <summary>
        /// 애니메이션 시작 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void animateButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = ((ListViewItem)this.targetComboBox.SelectedItem).Tag as Button;

            Point relativePoint = button.TransformToAncestor(this.contentStackPanel).Transform(new Point(0, 0));

            ScrollToPosition(relativePoint.X, relativePoint.Y);
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 버튼 생성하기 - CreateButton(index)

        /// <summary>
        /// 버튼 생성하기
        /// </summary>
        /// <param name="index">인덱스</param>
        /// <returns>버튼</returns>
        private Button CreateButton(int index)
        {
            Button button = new Button();

            button.Margin  = new Thickness(5);
            button.Height  = 30;
            button.Content = "버튼 " + index.ToString();

            return button;
        }

        #endregion
        #region 위치까지 스크롤하기 - ScrollToPosition(x, y)

        /// <summary>
        /// 위치까지 스크롤하기
        /// </summary>
        /// <param name="x">X</param>
        /// <param name="y">Y</param>
        private void ScrollToPosition(double x, double y)
        {
            DoubleAnimation xAnimation = new DoubleAnimation();

            xAnimation.From = this.animationScrollViewer.HorizontalOffset;
            xAnimation.To = x;
            xAnimation.DecelerationRatio = 0.2;
            xAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(1000));

            DoubleAnimation yAnimation = new DoubleAnimation();

            yAnimation.From              = this.animationScrollViewer.VerticalOffset;
            yAnimation.To                = y;
            yAnimation.DecelerationRatio = 0.2;
            yAnimation.Duration          = new Duration(TimeSpan.FromMilliseconds(500));

            Storyboard storyboard = new Storyboard();

            storyboard.Children.Add(xAnimation);
            storyboard.Children.Add(yAnimation);

            Storyboard.SetTarget(xAnimation, this.animationScrollViewer);
            Storyboard.SetTargetProperty(xAnimation, new PropertyPath(AnimationScrollViewer.CurrentHorizontalOffsetProperty));

            Storyboard.SetTarget(yAnimation, this.animationScrollViewer);
            Storyboard.SetTargetProperty(yAnimation, new PropertyPath(AnimationScrollViewer.CurrentVerticalOffsetProperty));

            storyboard.Begin();
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by 사용자 icodebroker

댓글을 달아 주세요