WPF2008/08/16 15:17

안녕하세요. 이번시간에는 아래 동영상과 같이 마우스를 사용해 스크롤 할 수 있는 Panel을 구현해보았습니다. 마치 IPhone에서 터치로 창을 제어하는 느낌이라 제목을 IPhone Scroll Panel이라고 써봤습니다. 만들고보니 Scroll Panel보단 SlidePanel이 더 어울리는거 같네요 -_- ㅋ



구현에 필요한 코드는 다음과 같습니다.

[XAML]

<Grid Width="320" Height="480">
    <Grid.Background>
        <ImageBrush ImageSource="Background.jpg"/>
    </Grid.Background>
    <Canvas ClipToBounds="True" Margin="0,82,0,40">
        <StackPanel Background="WhiteSmoke" Canvas.Top="0" x:Name="Panel">
            <StackPanel.Resources>
                <Style TargetType="Button">
                    <Setter Property="Height" Value="30"/>
                    <Setter Property="Width" Value="300"/>
                    <Setter Property="Margin" Value="10"/>
                </Style>
            </StackPanel.Resources>
        </StackPanel>   
    </Canvas>
</Grid>

[C#]

void Window1_Loaded(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < 30; i++)
    {
        Button Item = new Button();
        Item.Content = "ITEM #" + i.ToString();
        Panel.Children.Add(Item);
    }

    ScrollPanel ScrollPanel = new ScrollPanel(Panel);

}

[C# - ScrollPanel.cs]

public class ScrollPanel
{

    private const int MinimunRange = 30;
    private const int MinimumTime = 100;

    private FrameworkElement Target { get; set; }
    private FrameworkElement TargetParent { get; set; }

    private Point BeginPoint;
    private Point LastPoint;
    private DoubleAnimation MoveAnimation;
    private double LastMoveTime;

    public ScrollPanel(FrameworkElement TargetElement)
    {
        MoveAnimation = new DoubleAnimation();
        MoveAnimation.Duration = TimeSpan.FromMilliseconds(1000);
        MoveAnimation.DecelerationRatio = 0.8;

        Target = TargetElement;
        TargetParent = Target.Parent as FrameworkElement;
        Target.PreviewMouseMove += new MouseEventHandler(Target_MouseMove);
        Target.PreviewMouseDown += new MouseButtonEventHandler(Target_MouseDown);
        Target.PreviewMouseUp += new MouseButtonEventHandler(Target_MouseUp);

    }
    void Target_MouseUp(object sender, MouseButtonEventArgs e)
    {
        Target.ReleaseMouseCapture();
    }

    void Target_MouseDown(object sender, MouseButtonEventArgs e)
    {
        BeginPoint = e.GetPosition(Target);
        Target.CaptureMouse();
    }
    void Target_MouseMove(object sender, MouseEventArgs e)
    {

        if (e.LeftButton != MouseButtonState.Pressed) return;

        // 너무 빨리 움직였을경우
        if ((DateTime.Now.TimeOfDay.TotalMilliseconds - LastMoveTime) < MinimumTime) return;
        LastMoveTime = DateTime.Now.TimeOfDay.TotalMilliseconds;

        // 마우스가 제자리 일 경우
        Point CurrentPointParent = e.GetPosition(TargetParent);
        if (CurrentPointParent.Y == LastPoint.Y) return;
        LastPoint = CurrentPointParent;

        // 마우스가 너무 적게 움직였을 경우
        Point CurrentPoint = e.GetPosition(Target);
        double MovePosition = (CurrentPoint.Y - BeginPoint.Y);
        if (Math.Abs(MovePosition) < MinimunRange) return;

        MoveAnimation.By = MovePosition*1.5;
        Target.BeginAnimation(Canvas.TopProperty, MoveAnimation);

    }

}

XAML코드와 Window Loaded Event부분은 UI구성에 필요한 부분이므로 설명은 생략하도록 하겠습니다. ScrollPanel Class를 살펴보겠습니다. ScrollPanel은 생성자로 스크롤이 될 Target Control을 입력받으며 내부적으로 Target과 Target의 부모를 가지고 있습니다. 그리고 MouseEvent 가 발생할 경우 에 따라서 움직이는 Animation을 적용시켰습니다. 코드를 보고 이해가 안되는 부분이나 추가 설명이 필요하신 부분은 리플 달아주세요.

아래는 전체 소스코드 파일입니다.


사용자 삽입 이미지

 
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 곡스