첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestSolution.zip
다운로드

▶ Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestLibrary">
    <Style TargetType="{x:Type local:MonoButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <ControlTemplate.Resources>
                        <Geometry x:Key="CollapseGeometryKey">M 0 4 L 4 0 L 8 4</Geometry>
                        <Geometry x:Key="ExpandGeometryKey">M 0 1 L 4 5 L 8 1</Geometry>
                        <Geometry x:Key="CloseGeometryKey">M 1 1 L 7 7 M 7 1 L 1 7</Geometry>
                        <Geometry x:Key="LeftGeometryKey">M 8 4 L 0 4 L 4 0 M 0 4 L 4 8</Geometry>
                        <Geometry x:Key="RightGeometryKey">M 0 4 L 8 4 L 4 0 M 8 4 L 4 8</Geometry>
                        <Geometry x:Key="TopGeometryKey">M 0 4 L 4 0 L 4 8 M 4 0 L 8 4</Geometry>
                        <Geometry x:Key="BottomGeometryKey">M 4 0 L 4 8 L 8 4 M 4 8 L 0 4</Geometry>
                    </ControlTemplate.Resources>
                    <Grid Name="grid"
                            Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}">
                        <Ellipse Name="ellipse"
                                HorizontalAlignment="Stretch"
                                VerticalAlignment="Stretch"
                                StrokeThickness="2"
                                Stroke="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=RegularBrush}"
                                Fill="Transparent" />
                        <Path Name="path"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                StrokeThickness="2"
                                Stroke="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=RegularBrush}"
                                Fill="Transparent" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter
                                TargetName="ellipse"
                                Property="Stroke"
                                Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HoverBrush}" />
                            <Setter
                                TargetName="path"
                                Property="Stroke"
                                Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HoverBrush}" />
                        </Trigger>
                        <Trigger Property="Button.IsPressed" Value="True">
                            <Setter
                                TargetName="ellipse"
                                Property="Stroke"
                                Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PressBrush}" />
                            <Setter
                                TargetName="path"
                                Property="Stroke"
                                Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PressBrush}" />
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="ellipse" Property="Stroke" Value="DarkGray" />
                            <Setter TargetName="path"    Property="Stroke" Value="DarkGray" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Collapse">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource CollapseGeometryKey}" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Expand">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource ExpandGeometryKey}" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Close">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource CloseGeometryKey}" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Left">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource LeftGeometryKey}" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Top">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource TopGeometryKey}" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Right">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource RightGeometryKey}" />
                        </Trigger>
                        <Trigger Property="local:MonoButton.MonoButtonType" Value="Bottom">
                            <Setter
                                TargetName="path"
                                Property="Data"
                                Value="{StaticResource BottomGeometryKey}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style TargetType="{x:Type local:PanelControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate x:Name="controlTemplate" TargetType="ContentControl">
                    <Border x:Name="rootBorder"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*"    />
                            </Grid.RowDefinitions>
                            <Border Name="headerBorder" Grid.Row="0"
                                Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderVisibility}"
                                Padding="1"
                                Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderBackground}">
                                <DockPanel>
                                    <local:MonoButton x:Name="closeButton" DockPanel.Dock="Right"
                                        Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CloseButtonVisibility}"
                                        VerticalAlignment="Center"
                                        Margin="1"
                                        Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonWidth}"
                                        Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonHeight}"
                                        MonoButtonType="Close"
                                        RegularBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonRegular}"
                                        HoverBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonHover}"
                                        PressBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonPress}" />
                                    <local:MonoButton x:Name="expandButton" DockPanel.Dock="Right"
                                        Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ExpandButtonVisibility}"
                                        VerticalAlignment="Center"
                                        Margin="1"
                                        Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonWidth}"
                                        Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonHeight}"
                                        MonoButtonType="Collapse"
                                        RegularBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonRegular}"
                                        HoverBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonHover}"
                                        PressBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderButtonPress}" />
                                    <Image x:Name="headerIconImage" DockPanel.Dock="Left"
                                        Margin="5 0 0 0"
                                        Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderIconWidth}"
                                        Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderIconHeight}"
                                        Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=HeaderIcon}" />
                                    <ContentPresenter
                                        VerticalAlignment="Center"
                                        Margin="5 0 0 0"
                                        Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Header}" />
                                </DockPanel>
                            </Border>
                            <ContentPresenter Name="contentPresenter" Grid.Row="1"
                                Margin="{TemplateBinding Padding}"
                                Content="{TemplateBinding Content}" />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="local:PanelControl.IsExpanded" Value="False">
                            <Setter TargetName="expandButton" Property="MonoButtonType" Value="Expand" />
                        </Trigger>
                        <Trigger Property="local:PanelControl.IsEnabled" Value="False">
                            <Setter TargetName="rootBorder"   Property="BorderBrush" Value="DarkGray"  />
                            <Setter TargetName="headerBorder" Property="Background"  Value="LightGray" />
                        </Trigger>
                        <Trigger Property="local:PanelControl.HeaderIcon" Value="{x:Null}">
                            <Setter TargetName="headerIconImage"   Property="Visibility" Value="Collapsed" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

 

728x90

 

▶ PanelControl.cs

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

namespace TestLibrary
{
    /// <summary>
    /// 패널 컨트롤
    /// </summary>
    public class PanelControl : ContentControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Event
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 확장 여부 변경시 이벤트 - ExpandedChanged

        /// <summary>
        /// 확장 여부 변경시 이벤트
        /// </summary>
        public event EventHandler ExpandedChanged;

        #endregion
        #region 확장 버튼 클릭시 이벤트 - ExpandButtonClick

        /// <summary>
        /// 확장 버튼 클릭시 이벤트
        /// </summary>
        public event EventHandler ExpandButtonClick;

        #endregion
        #region 닫기 버튼 클릭시 이벤트 - CloseButtonClick

        /// <summary>
        /// 닫기 버튼 클릭시 이벤트
        /// </summary>
        public event EventHandler CloseButtonClick;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 헤더 표시 여부 의존 속성 - HeaderVisibilityProperty

        /// <summary>
        /// 헤더 표시 여부 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderVisibilityProperty;

        #endregion
        #region 헤더 배경색 의존 속성 - HeaderBackgroundProperty

        /// <summary>
        /// 헤더 배경색 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderBackgroundProperty;

        #endregion
        #region 헤더 아이콘 너비 의존 속성 - HeaderIconWidthProperty

        /// <summary>
        /// 헤더 아이콘 너비 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderIconWidthProperty;

        #endregion
        #region 헤더 아이콘 높이 의존 속성 - HeaderIconHeightProperty

        /// <summary>
        /// 헤더 아이콘 높이 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderIconHeightProperty;

        #endregion
        #region 헤더 아이콘 의존 속성 - HeaderIconProperty

        /// <summary>
        /// 헤더 아이콘 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderIconProperty;

        #endregion
        #region 헤더 의존 속성 - HeaderProperty

        /// <summary>
        /// 헤더 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderProperty;

        #endregion
        #region 헤더 버튼 REGULAR 의존 속성 - HeaderButtonRegularProperty

        /// <summary>
        /// 헤더 버튼 REGULAR 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderButtonRegularProperty;

        #endregion
        #region 헤더 버튼 HOVER 의존 속성 - HeaderButtonHoverProperty

        /// <summary>
        /// 헤더 버튼 HOVER 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderButtonHoverProperty;

        #endregion
        #region 헤더 버튼 PRESS 의존 속성 - HeaderButtonPressProperty

        /// <summary>
        /// 헤더 버튼 PRESS 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderButtonPressProperty;

        #endregion
        #region 확장 버튼 표시 여부 의존 속성 - ExpandButtonVisibilityProperty

        /// <summary>
        /// 확장 버튼 표시 여부 의존 속성
        /// </summary>
        public static readonly DependencyProperty ExpandButtonVisibilityProperty;

        #endregion
        #region 닫기 버튼 표시 여부 의존 속성 - CloseButtonVisibilityProperty

        /// <summary>
        /// 닫기 버튼 표시 여부 의존 속성
        /// </summary>
        public static readonly DependencyProperty CloseButtonVisibilityProperty;

        #endregion
        #region 헤더 버튼 너비 의존 속성 - HeaderButtonWidthProperty

        /// <summary>
        /// 헤더 버튼 너비 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderButtonWidthProperty;

        #endregion
        #region 헤더 버튼 높이 의존 속성 - HeaderButtonHeightProperty

        /// <summary>
        /// 헤더 버튼 높이 의존 속성
        /// </summary>
        public static readonly DependencyProperty HeaderButtonHeightProperty;

        #endregion
        #region 애니메이션 사용 여부 의존 속성 - UseAnimationProperty

        /// <summary>
        /// 애니메이션 사용 여부 의존 속성
        /// </summary>
        public static readonly DependencyProperty UseAnimationProperty;

        #endregion
        #region 확장 여부 의존 속성 - IsExpandedProperty

        /// <summary>
        /// 확장 여부 의존 속성
        /// </summary>
        public static readonly DependencyProperty IsExpandedProperty;

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 원본 높이
        /// </summary>
        private double originalHeight = 0;

        /// <summary>
        /// 헤더 Border
        /// </summary>
        private Border headerBorder = null;

        /// <summary>
        /// 이전 클릭 시간
        /// </summary>
        private DateTime previousClickTime = DateTime.Now;

        /// <summary>
        /// DoubleAnimation
        /// </summary>
        private DoubleAnimation doubleAnimation;

        /// <summary>
        /// Storyboard
        /// </summary>
        private Storyboard storyboard;

        /// <summary>
        /// 애니메이션 여부
        /// </summary>
        private bool isAnimating = false;

        #endregion

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

        #region 헤더 표시 여부 - HeaderVisibility

        /// <summary>
        /// 헤더 표시 여부
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 표시 여부를 가져오거나 설정합니다.")]
        public Visibility HeaderVisibility
        {
            get
            {
                return (Visibility)GetValue(HeaderVisibilityProperty);
            }
            set
            {
                SetValue(HeaderVisibilityProperty, value);
            }
        }

        #endregion
        #region 헤더 배경색 - HeaderBackground

        /// <summary>
        /// 헤더 배경색
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 배경색을 가져오거나 설정합니다.")]
        public Brush HeaderBackground
        {
            get
            {
                return (Brush)GetValue(HeaderBackgroundProperty);
            }
            set
            {
                SetValue(HeaderBackgroundProperty, value);
            }
        }

        #endregion
        #region 헤더 아이콘 너비 - HeaderIconWidth

        /// <summary>
        /// 헤더 아이콘 너비
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 아이콘 너비를 가져오거나 설정합니다.")]
        public double HeaderIconWidth
        {
            get
            {
                return (double)GetValue(HeaderIconWidthProperty);
            }
            set
            {
                SetValue(HeaderIconWidthProperty, value);
            }
        }

        #endregion
        #region 헤더 아이콘 높이 - HeaderIconHeight

        /// <summary>
        /// 헤더 아이콘 높이
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 아이콘 높이를 가져오거나 설정합니다.")]
        public double HeaderIconHeight
        {
            get
            {
                return (double)GetValue(HeaderIconHeightProperty);
            }
            set
            {
                SetValue(HeaderIconHeightProperty, value);
            }
        }

        #endregion
        #region 헤더 아이콘 - HeaderIcon

        /// <summary>
        /// 헤더 아이콘
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 아이콘을 가져오거나 설정합니다.")]
        public ImageSource HeaderIcon
        {
            get
            {
                return (ImageSource)GetValue(HeaderIconProperty);
            }
            set
            {
                SetValue(HeaderIconProperty, value);
            }
        }

        #endregion
        #region 헤더 - Header

        /// <summary>
        /// 헤더
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더를 가져오거나 설정합니다.")]
        public object Header
        {
            get
            {
                return (object)GetValue(HeaderProperty);
            }
            set
            {
                SetValue(HeaderProperty, value);
            }
        }

        #endregion
        #region 헤더 버튼 REGULAR - HeaderButtonRegular

        /// <summary>
        /// 헤더 버튼 REGULAR
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 버튼 REGULAR를 가져오거나 설정합니다.")]
        public Brush HeaderButtonRegular
        {
            get
            {
                return (Brush)GetValue(HeaderButtonRegularProperty);
            }
            set
            {
                SetValue(HeaderButtonRegularProperty, value);
            }
        }

        #endregion
        #region 헤더 버튼 HOVER - HeaderButtonHover

        /// <summary>
        /// 헤더 버튼 HOVER
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 버튼 HOVER를 가져오거나 설정합니다.")]
        public Brush HeaderButtonHover
        {
            get
            {
                return (Brush)GetValue(HeaderButtonHoverProperty);
            }
            set
            {
                SetValue(HeaderButtonHoverProperty, value);
            }
        }

        #endregion
        #region 헤더 버튼 PRESS - HeaderButtonPress

        /// <summary>
        /// 헤더 버튼 PRESS
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 버튼 PRESS를 가져오거나 설정합니다.")]
        public Brush HeaderButtonPress
        {
            get
            {
                return (Brush)GetValue(HeaderButtonPressProperty);
            }
            set
            {
                SetValue(HeaderButtonPressProperty, value);
            }
        }

        #endregion
        #region 확장 버튼 표시 여부 - ExpandButtonVisibility

        /// <summary>
        /// 확장 버튼 표시 여부
        /// </summary>
        [Category("PanelControl")]
        [Description("확장 버튼 표시 여부를 가져오거나 설정합니다.")]
        public Visibility ExpandButtonVisibility
        {
            get
            {
                return (Visibility)GetValue(ExpandButtonVisibilityProperty);
            }
            set
            {
                SetValue(ExpandButtonVisibilityProperty, value);
            }
        }

        #endregion
        #region 닫기 버튼 표시 여부 - CloseButtonVisibility

        /// <summary>
        /// 닫기 버튼 표시 여부
        /// </summary>
        [Category("PanelControl")]
        [Description("닫기 버튼 표시 여부를 가져오거나 설정합니다.")]
        public Visibility CloseButtonVisibility
        {
            get
            {
                return (Visibility)GetValue(CloseButtonVisibilityProperty);
            }
            set
            {
                SetValue(CloseButtonVisibilityProperty, value);
            }
        }

        #endregion
        #region 헤더 버튼 너비 - HeaderButtonWidth

        /// <summary>
        /// 헤더 버튼 너비
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 버튼 너비를 가져오거나 설정합니다.")]
        public double HeaderButtonWidth
        {
            get
            {
                return (double)GetValue(HeaderButtonWidthProperty);
            }
            set
            {
                SetValue(HeaderButtonWidthProperty, value);
            }
        }

        #endregion
        #region 헤더 버튼 높이 - HeaderButtonHeight

        /// <summary>
        /// 헤더 버튼 높이
        /// </summary>
        [Category("PanelControl")]
        [Description("헤더 버튼 높이를 가져오거나 설정합니다.")]
        public double HeaderButtonHeight
        {
            get
            {
                return (double)GetValue(HeaderButtonHeightProperty);
            }
            set
            {
                SetValue(HeaderButtonHeightProperty, value);
            }
        }

        #endregion
        #region 애니메이션 사용 여부 - UseAnimation

        /// <summary>
        /// 애니메이션 사용 여부
        /// </summary>
        [Category("PanelControl")]
        [Description("애니메이션 사용 여부를 가져오거나 설정합니다.")]
        public bool UseAnimation
        {
            get
            {
                return (bool)GetValue(UseAnimationProperty);
            }
            set
            {
                SetValue(UseAnimationProperty, value);
            }
        }

        #endregion
        #region 확장 여부 - IsExpanded

        /// <summary>
        /// 확장 여부
        /// </summary>
        [Category("PanelControl")]
        [Description("확장 여부를 가져오거나 설정합니다.")]
        public bool IsExpanded
        {
            get
            {
                return (bool)GetValue(IsExpandedProperty);
            }
            set
            {
                SetValue(IsExpandedProperty, value);
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Static

        #region 생성자 - PanelControl()

        /// <summary>
        /// 생성자
        /// </summary>
        static PanelControl()
        {
            HeaderVisibilityProperty = UIHelper.RegisterDependencyProperty
            (
                Visibility.Visible,
                false,
                false,
                false,
                true,
                null,
                "HeaderVisibility",
                typeof(Visibility),
                typeof(PanelControl),
                null
            );

            HeaderBackgroundProperty = UIHelper.RegisterDependencyProperty
            (
                Brushes.RoyalBlue,
                false,
                false,
                false,
                true,
                null,
                "HeaderBackground",
                typeof(Brush),
                typeof(PanelControl),
                null
            );

            HeaderIconWidthProperty = UIHelper.RegisterDependencyProperty
            (
                16d,
                false,
                false,
                false,
                true,
                null,
                "HeaderIconWidth",
                typeof(double),
                typeof(PanelControl),
                null
            );

            HeaderIconHeightProperty = UIHelper.RegisterDependencyProperty
            (
                16d,
                false,
                false,
                false,
                true,
                null,
                "HeaderIconHeight",
                typeof(double),
                typeof(PanelControl),
                null
            );

            HeaderIconProperty = UIHelper.RegisterDependencyProperty
            (
                null,
                false,
                false,
                false,
                true,
                null,
                "HeaderIcon",
                typeof(ImageSource),
                typeof(PanelControl),
                null
            );

            HeaderProperty = UIHelper.RegisterDependencyProperty
            (
                null,
                false,
                false,
                false,
                true,
                null,
                "Header",
                typeof(object),
                typeof(PanelControl),
                null
            );

            HeaderButtonRegularProperty = UIHelper.RegisterDependencyProperty
            (
                Brushes.White,
                false,
                false,
                false,
                true,
                null,
                "HeaderButtonRegular",
                typeof(Brush),
                typeof(PanelControl),
                null
            );

            HeaderButtonHoverProperty = UIHelper.RegisterDependencyProperty
            (
                Brushes.Yellow,
                false,
                false,
                false,
                true,
                null,
                "HeaderButtonHover",
                typeof(Brush),
                typeof(PanelControl),
                null
            );

            HeaderButtonPressProperty = UIHelper.RegisterDependencyProperty
            (
                Brushes.Gold,
                false,
                false,
                false,
                true,
                null,
                "HeaderButtonPress",
                typeof(Brush),
                typeof(PanelControl),
                null
            );

            ExpandButtonVisibilityProperty = UIHelper.RegisterDependencyProperty
            (
                Visibility.Visible,
                false,
                false,
                false,
                true,
                null,
                "ExpandButtonVisibility",
                typeof(Visibility),
                typeof(PanelControl),
                null
            );

            CloseButtonVisibilityProperty = UIHelper.RegisterDependencyProperty
            (
                Visibility.Visible,
                false,
                false,
                false,
                true,
                null,
                "CloseButtonVisibility",
                typeof(Visibility),
                typeof(PanelControl),
                null
            );

            HeaderButtonWidthProperty = UIHelper.RegisterDependencyProperty
            (
                20d,
                false,
                false,
                false,
                true,
                null,
                "HeaderButtonWidth",
                typeof(double),
                typeof(PanelControl),
                null
            );

            HeaderButtonHeightProperty = UIHelper.RegisterDependencyProperty
            (
                20d,
                false,
                false,
                false,
                true,
                null,
                "HeaderButtonHeight",
                typeof(double),
                typeof(PanelControl),
                null
            );

            UseAnimationProperty = UIHelper.RegisterDependencyProperty
            (
                true,
                false,
                false,
                false,
                true,
                null,
                "UseAnimation",
                typeof(bool),
                typeof(PanelControl),
                null
            );

            IsExpandedProperty = UIHelper.RegisterDependencyProperty
            (
                true,
                false,
                false,
                false,
                true,
                isExpandedPropertyChangedCallback,
                "IsExpanded",
                typeof(bool),
                typeof(PanelControl),
                null
            );

            DefaultStyleKeyProperty.OverrideMetadata(typeof(PanelControl), new FrameworkPropertyMetadata(typeof(PanelControl)));
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - PanelControl()

        /// <summary>
        /// 생성자
        /// </summary>
        public PanelControl()
        {
            NameScope.SetNameScope(this, new NameScope());

            RegisterName("contentControl", this);

            #region 스토리 보드를 설정합니다.

            this.doubleAnimation = new DoubleAnimation();

            this.doubleAnimation.AutoReverse  = false;
            this.doubleAnimation.Duration     = TimeSpan.FromSeconds(0.1);
            this.doubleAnimation.FillBehavior = FillBehavior.HoldEnd;

            Storyboard.SetTargetName(this.doubleAnimation, "contentControl");

            Storyboard.SetTargetProperty(this.doubleAnimation, new PropertyPath(PanelControl.HeightProperty));

            this.storyboard = new Storyboard();

            this.storyboard.Children.Add(this.doubleAnimation);

            #endregion

            this.storyboard.Completed += storyboard_Completed;

            BorderBrush     = Brushes.RoyalBlue;
            BorderThickness = new Thickness(2);

            Loaded += ContentControl_Loaded;
        }

        #endregion

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

        #region 확장 여부 속성 변경시 콜백 처리하기 - isExpandedPropertyChangedCallback(e, e)

        /// <summary>
        /// 확장 여부 속성 변경시 콜백 처리하기
        /// </summary>
        /// <param name="d">의존 객체</param>
        /// <param name="e">이벤트 인자</param>
        private static void isExpandedPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PanelControl expander = d as PanelControl;

            bool newValue = (bool)e.NewValue;

            if(newValue)
            {
                if(expander.UseAnimation)
                {
                    expander.doubleAnimation.From = expander.headerBorder.ActualHeight +
                        (expander.BorderThickness.Top + expander.BorderThickness.Bottom);
                    expander.doubleAnimation.To   = expander.originalHeight;

                    expander.storyboard.Begin(expander);
                }
                else
                {
                    expander.Height = expander.originalHeight;
                }
            }
            else
            {
                expander.originalHeight = expander.ActualHeight;

                if(expander.UseAnimation)
                {
                    expander.doubleAnimation.From = expander.originalHeight;
                    expander.doubleAnimation.To   = expander.headerBorder.ActualHeight +
                        (expander.BorderThickness.Top + expander.BorderThickness.Bottom);

                    expander.storyboard.Begin(expander);
                }
                else
                {
                    expander.Height = expander.headerBorder.ActualHeight +
                        (expander.BorderThickness.Top + expander.BorderThickness.Bottom);
                }
            }

            expander.FireExpandedChanged();
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Protected
        ////////////////////////////////////////////////////////////////////// Function

        #region 확장 여부 변경시 이벤트 발생시키기 - FireExpandedChanged()

        /// <summary>
        /// 확장 여부 변경시 이벤트 발생시키기
        /// </summary>
        protected void FireExpandedChanged()
        {
            if(ExpandedChanged != null)
            {
                ExpandedChanged(this, EventArgs.Empty);
            }
        }

        #endregion
        #region Expand 버튼 클릭시 이벤트 발생시키기 - FireExpandButtonClick()

        /// <summary>
        /// Expand 버튼 클릭시 이벤트 발생시키기
        /// </summary>
        protected void FireExpandButtonClick()
        {
            if(ExpandButtonClick != null)
            {
                ExpandButtonClick(this, EventArgs.Empty);
            }
        }

        #endregion
        #region Close 버튼 클릭시 이벤트 발생시키기 - FireCloseButtonClick()

        /// <summary>
        /// Close 버튼 클릭시 이벤트 발생시키기
        /// </summary>
        protected void FireCloseButtonClick()
        {
            if(CloseButtonClick != null)
            {
                CloseButtonClick(this, EventArgs.Empty);
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private
        ////////////////////////////////////////////////////////////////////// Event

        #region 컨텐트 컨트롤 로드시 처리하기 - ContentControl_Loaded(sender, e)

        /// <summary>
        /// 컨텐트 컨트롤 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void ContentControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.headerBorder = Template.FindName("headerBorder", this) as Border;

            this.headerBorder.MouseLeftButtonUp += headerBorder_MouseLeftButtonUp;

            MonoButton expandButton = Template.FindName("expandButton", this) as MonoButton;
            MonoButton closeButton  = Template.FindName("closeButton" , this) as MonoButton;

            expandButton.Click += expandButton_Click;
            closeButton.Click  += closeButton_Click;
        }

        #endregion
        #region 헤더 Border 마우스 왼쪽 버튼 UP 처리하기 - headerBorder_MouseLeftButtonUp(sender, e)

        /// <summary>
        /// 헤더 Border 마우스 왼쪽 버튼 UP 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void headerBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            DateTime currentClickTime = DateTime.Now;

            TimeSpan timeSpan = currentClickTime - this.previousClickTime;

            if(timeSpan.Milliseconds < 200)
            {
                ProcessExpand();

                currentClickTime = currentClickTime.AddMilliseconds(-200);
            }

            this.previousClickTime = currentClickTime;
        }

        #endregion
        #region 확장 버튼 클릭시 처리하기 - expandButton_Click(sender, e)

        /// <summary>
        /// 확장 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void expandButton_Click(object sender, RoutedEventArgs e)
        {
            ProcessExpand();

            FireExpandedChanged();
        }

        #endregion
        #region 닫기 버튼 클릭시 처리하기 - closeButton_Click(sender, e)

        /// <summary>
        /// 닫기 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void closeButton_Click(object sender, RoutedEventArgs e)
        {
            FireCloseButtonClick();
        }

        #endregion
        #region 스토리보드 완료시 처리하기 - storyboard_Completed(sender, e)

        /// <summary>
        /// 스토리보드 완료시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void storyboard_Completed(object sender, EventArgs e)
        {
            this.isAnimating = false;
        }

        #endregion

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

        #region 확장 처리하기 - ProcessExpand()

        /// <summary>
        /// 확장 처리하기
        /// </summary>
        private void ProcessExpand()
        {
            if(UseAnimation)
            {
                if(!this.isAnimating)
                {
                    this.isAnimating = true;

                    IsExpanded = !IsExpanded;
                }
            }
            else
            {
                IsExpanded = !IsExpanded;
            }

            FireExpandButtonClick();
        }

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

댓글을 달아 주세요