■ Grid 클래스 : 환형 패널 사용하기
------------------------------------------------------------------------------------------------------------------------
▶ 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>
|
------------------------------------------------------------------------------------------------------------------------
'C# > WPF' 카테고리의 다른 글
[C#/WPF] Canvas 클래스 : 타원 도형 추가하기 (0) | 2020.12.26 |
---|---|
[C#/WPF] Canvas 클래스 : 사각형 도형 추가하기 (0) | 2020.12.26 |
[C#/WPF] MarkupExtension 클래스 : 마크업 확장 사용하기 (0) | 2020.12.15 |
[C#/WPF] Image 클래스 : LayoutUpdated 이벤트를 사용해 이미지 픽셀 보정하기 (0) | 2020.12.13 |
[C#/WPF] FrameworkElement 클래스 : 장평을 설정하는 커스텀 텍스트 블럭 사용하기 (0) | 2020.12.13 |
[C#/WPF] Grid 클래스 : 환형 패널 사용하기 (0) | 2020.12.12 |
[C#/WPF] ObjectDataProvider 엘리먼트 : Colors 클래스의 색상 정적 속성 구하기 (0) | 2020.12.07 |
[C#/WPF] 파노라마 뷰 사용하기 (0) | 2020.12.06 |
[C#/WPF] TabControl 클래스 : FADE IN/OUT 탭 컨트롤 사용하기 (0) | 2020.12.06 |
[C#/WPF] FrameworkElement 엘리먼트 : FocusVisualStyle 속성을 사용해 포커스 사각형 제거하기 (0) | 2020.12.05 |
[C#/WPF] UIElement 클래스 : MouseMove 이벤트를 사용해 마우스 이동시 애니메이션 설정하기 (0) | 2020.12.05 |
댓글을 달아 주세요