첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ Grid 클래스 : 환형 패널 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


FrameworkElementExtention.cs

 

 

using System.Windows;

using System.Windows.Media;

 

namespace TestProject

{

    /// <summary>

    /// 프레임워크 엘리먼트 확장

    /// </summary>

    public static class FrameworkElementExtention

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 회전하기 - Rotate(source, angle)

 

        /// <summary>

        /// 회전하기

        /// </summary>

        /// <param name="source">소스 엘리먼트</param>

        /// <param name="angle">각도</param>

        public static void Rotate(this FrameworkElement source, double angle)

        {

            source.RenderTransformOrigin = new Point(0.5, 1);

 

            source.HorizontalAlignment = HorizontalAlignment.Center;

            source.VerticalAlignment   = VerticalAlignment.Center;

 

            if(source.RenderTransform is RotateTransform)

            {

                (source.RenderTransform as RotateTransform).Angle = angle;

            }

            else

            {

                source.RenderTransform = new RotateTransform(angle);

            }

        }

 

        #endregion

    }

}

 

 

CircularGrid.cs

 

 

using System;

using System.Windows;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Controls;

using System.Windows.Media.Animation;

 

namespace TestProject

{

    /// <summary>

    /// 환형 그리드

    /// </summary>

    public class CircularGrid : Grid

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 회전 변환 - RotateTransform

 

        /// <summary>

        /// 회전 변환

        /// </summary>

        public RotateTransform RotateTransform { get; private set; }

 

        #endregion

        #region 이동 변환 - TranslateTransform

 

        /// <summary>

        /// 이동 변환

        /// </summary>

        public TranslateTransform TranslateTransform { get; private set; }

 

        #endregion

        #region 항목 각도 - ItemAngle

 

        /// <summary>

        /// 항목 각도

        /// </summary>

        public double ItemAngle { get; private set; }

 

        #endregion

        #region 항목 너비 - ItemWidth

 

        /// <summary>

        /// 항목 너비

        /// </summary>

        public double ItemWidth { get; private set; }

 

        #endregion

        #region 항목 높이 - ItemHeight

 

        /// <summary>

        /// 항목

        /// </summary>

        public double ItemHeight { get; private set; }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - CircularGrid()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public CircularGrid()

        {

            RenderTransformOrigin = new Point(0.5, 0.5);

 

            TransformGroup transformGroup = new TransformGroup();

 

            RotateTransform    = new RotateTransform();

            TranslateTransform = new TranslateTransform();

            

            transformGroup.Children.Add(RotateTransform   );

            transformGroup.Children.Add(TranslateTransform);

 

            RenderTransform = transformGroup;

 

            PreviewMouseWheel += Grid_PreviewMouseWheel;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 그리드 프리뷰 마우스 DOWN 처리하기 - Grid_PreviewMouseDown(sender, e)

 

        /// <summary>

        /// 그리드 프리뷰 마우스 DOWN 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)

        {

            FrameworkElement selectedItem = sender as FrameworkElement;

 

            double currentAngle     = RotateTransform.Angle % 360 ;

            int    itemCount        = Children.Count;

            int    currentIndex     = itemCount - (int)(currentAngle / ItemAngle);

            int    selectedIndex    = Children.IndexOf(selectedItem);

            int    distance         = selectedIndex - currentIndex;

            int    absoluteDistance = Math.Abs(distance);

            double rotateAngle      = 0;

 

            if(distance > 0)

            {

                if(absoluteDistance > itemCount / 2)

                {

                    rotateAngle = (itemCount - absoluteDistance) * ItemAngle;

                }

                else

                {

                    rotateAngle = -(absoluteDistance * ItemAngle);

                }

            }

            else

            {

                if(absoluteDistance > itemCount / 2)

                {

                    rotateAngle = -(itemCount - absoluteDistance) * ItemAngle;

                }

                else

                {

                    rotateAngle = absoluteDistance * ItemAngle;

                }

            }

 

            DoubleAnimation angleAnimation = new DoubleAnimation()

            {

                SpeedRatio        = 2,

                AccelerationRatio = 0.7

            };

 

            angleAnimation.By = rotateAngle;

 

            RotateTransform.BeginAnimation(RotateTransform.AngleProperty, angleAnimation, HandoffBehavior.Compose);

        }

 

        #endregion

        #region 그리드 프리뷰 마우스 휠 처리하기 - Grid_PreviewMouseWheel(sender, e)

 

        /// <summary>

        /// 그리드 프리뷰 마우스 휠 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Grid_PreviewMouseWheel(object sender, MouseWheelEventArgs e)

        {

            DoubleAnimation angleAnimation = new DoubleAnimation()

            {

                SpeedRatio        = 2,

                AccelerationRatio = 0.7

            };

 

            angleAnimation.By = (e.Delta > 0 ? -ItemAngle : ItemAngle);

 

            RotateTransform.BeginAnimation(RotateTransform.AngleProperty, angleAnimation, HandoffBehavior.Compose);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 비주얼 자식 컬렉션 변경시 처리하기 - OnVisualChildrenChanged(addedObject, removedObject)

 

        /// <summary>

        /// 비주얼 자식 컬렉션 변경시 처리하기

        /// </summary>

        /// <param name="addedObject">추가 객체</param>

        /// <param name="removedObject">제거 객체</param>

        protected override void OnVisualChildrenChanged(DependencyObject addedObject, DependencyObject removedObject)

        {

            if(addedObject != null)

            {

                (addedObject as FrameworkElement).PreviewMouseDown +=  Grid_PreviewMouseDown;

            }

            else if(removedObject != null)

            {

                (addedObject as FrameworkElement).PreviewMouseDown -= Grid_PreviewMouseDown;

            }

 

            base.OnVisualChildrenChanged(addedObject, removedObject);

 

            UpdateList();

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region 리스트 업데이트하기 - UpdateList()

 

        /// <summary>

        /// 리스트 업데이트하기

        /// </summary>

        private void UpdateList()

        {

            if(!IsInitialized)

            {

                return;

            }

 

            int itemCount = Children.Count;

 

            ItemAngle = 360.0 / itemCount;

 

            if(IsItemsHost == true)

            {

                FrameworkElement Parent = TemplatedParent as FrameworkElement;

 

                ItemWidth  = (Parent.Width * Math.PI) / (itemCount * 1.5);

                ItemHeight = Parent.Height / 2;

            }

            else

            {

                ItemWidth  = (this.ActualWidth * Math.PI) / (itemCount * 1.5);

                ItemHeight = this.ActualHeight / 2;

            }

 

            int i = 0;

            

            foreach(FrameworkElement child in Children)

            {

                child.Width  = ItemWidth;

                child.Height = ItemHeight;

 

                child.Rotate(i * ItemAngle);

 

                i++;

            }

 

            TranslateTransform.Y = -ItemHeight / 2;

 

            RotateTransform.CenterY = ItemHeight / 2;

        }

 

        #endregion

    }

}

 

 

MainWindow.xaml.cs

 

 

<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="Grid 클래스 : 환형 패널 사용하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Grid>

        <ListBox Name="listBox"

            Width="400"

            Height="400">

            <ListBox.Resources>

                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"

                    Color="Transparent" />

                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"

                    Color="Transparent" />

            </ListBox.Resources>

            <ListBox.Template>

                <ControlTemplate>

                    <local:CircularGrid IsItemsHost="True" />

                </ControlTemplate>

            </ListBox.Template>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="맥주"

                    Source="IMAGE/beer.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="메달"

                    Source="IMAGE/medal.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="연필"

                    Source="IMAGE/pencil.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="방사능"

                    Source="IMAGE/radiation.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="반지"

                    Source="IMAGE/ring.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="맥주"

                    Source="IMAGE/beer.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="메달"

                    Source="IMAGE/medal.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="연필"

                    Source="IMAGE/pencil.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="방사능"

                    Source="IMAGE/radiation.png" />

            </Grid>

            <Grid>

                <Rectangle

                    Width="40"

                    Height="100"

                    Fill="Gray"

                    Opacity="0.5" />

                <Image

                    Width="32"

                    Height="32"

                    Tag="반지"

                    Source="IMAGE/ring.png" />

            </Grid>

        </ListBox>

        <TextBlock

            HorizontalAlignment="Center"

            VerticalAlignment="Center"

            FontSize="20"

            FontWeight="Bold"

            Text="{Binding ElementName=listBox, Path=SelectedValue.Children[1].Tag}" />

    </Grid>

</Window>

 

------------------------------------------------------------------------------------------------------------------------

728x90
반응형
Posted by 사용자 icodebroker
TAG , ,

댓글을 달아 주세요