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

TestProject.zip
0.01MB

▶ ListBoxItemSlideDirection.cs

namespace TestProject
{
    /// <summary>
    /// 리스트 박스 항목 슬라이드 방향
    /// </summary>
    public enum ListBoxItemSlideDirection
    {
        /// <summary>
        /// 왼쪽
        /// </summary>
        Left,

        /// <summary>
        /// 위쪽
        /// </summary>
        Up,

        /// <summary>
        /// 오른쪽
        /// </summary>
        Right,

        /// <summary>
        /// 아래쪽
        /// </summary>
        Down
    }
}

 

728x90

 

▶ SlidingListBox.cs

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

namespace TestProject
{
    /// <summary>
    /// 슬라이딩 리스트 박스
    /// </summary>
    public class SlidingListBox : ListBox
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 슬라이드 방향 속성 - SlideDirectionProperty

        /// <summary>
        /// 슬라이드 방향 속성
        /// </summary>
        public static readonly DependencyProperty SlideDirectionProperty = DependencyProperty.Register
        (
            "SlideDirection",
            typeof(ListBoxItemSlideDirection),
            typeof(SlidingListBox),
            new UIPropertyMetadata(ListBoxItemSlideDirection.Right)
        );

        #endregion
        #region 슬라이드 거리 속성 - SlideDistanceProperty

        /// <summary>
        /// 슬라이드 거리 속성
        /// </summary>
        public static readonly DependencyProperty SlideDistanceProperty = DependencyProperty.Register
        (
            "SlideDistance",
            typeof(double),
            typeof(SlidingListBox),
            new UIPropertyMetadata
            (
                20.0,
                NumericPropertyChangedCallback<double>
            )
        );

        #endregion
        #region 슬라이드 지속 시간 속성 - SlideDurationProperty

        /// <summary>
        /// 슬라이드 지속 시간 속성
        /// </summary>
        public static readonly DependencyProperty SlideDurationProperty = DependencyProperty.Register
        (
            "SlideDuration",
            typeof(int),
            typeof(SlidingListBox),
            new UIPropertyMetadata
            (
                200,
                NumericPropertyChangedCallback<int>
            )
        );

        #endregion

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

        #region 슬라이드 방향 - SlideDirection

        /// <summary>
        /// 슬라이드 방향
        /// </summary>
        public ListBoxItemSlideDirection SlideDirection
        {
            get
            {
                return (ListBoxItemSlideDirection)GetValue(SlideDirectionProperty);
            }
            set
            {
                SetValue(SlideDirectionProperty, value);
            }
        }

        #endregion
        #region 슬라이드 거리 - SlideDistance

        /// <summary>
        /// 슬라이드 거리
        /// </summary>
        public double SlideDistance
        {
            get
            {
                return (double)GetValue(SlideDistanceProperty);
            }
            set
            {
                SetValue(SlideDistanceProperty, value);
            }
        }

        #endregion
        #region 슬라이드 지속 시간 - SlideDuration

        /// <summary>
        /// 슬라이드 지속 시간
        /// </summary>
        public int SlideDuration
        {
            get
            {
                return (int)GetValue(SlideDurationProperty);
            }
            set
            {
                SetValue(SlideDurationProperty, value);
            }
        }

        #endregion

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

        #region 숫자 속성 변경시 콜백 처리하기 - NumericPropertyChangedCallback<T>(d, e)

        /// <summary>
        /// 숫자 속성 변경시 콜백 처리하기
        /// </summary>
        /// <typeparam name="T">속성 타입</typeparam>
        /// <param name="d">의존 객체</param>
        /// <param name="e">이벤트 인자</param>
        private static void NumericPropertyChangedCallback<T>(DependencyObject d, DependencyPropertyChangedEventArgs e) where T : IComparable
        {
            if(((T)e.NewValue).CompareTo(default(T)) < 0)
            {
                throw new ArgumentOutOfRangeException(e.Property.Name);
            }
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Protected

        #region 선택 변경시 처리하기 - OnSelectionChanged(e)

        /// <summary>
        /// 선택 변경시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);

            ItemContainerGenerator generator = this.ItemContainerGenerator;

            if(generator.Status != GeneratorStatus.ContainersGenerated)
            {
                return;
            }

            for(int i = 0; i < Items.Count; ++i)
            {
                ListBoxItem item = generator.ContainerFromIndex(i) as ListBoxItem;

                if(VisualTreeHelper.GetChildrenCount(item) == 0)
                {
                    continue;
                }

                Border rootBorder = VisualTreeHelper.GetChild(item, 0) as Border;

                if(rootBorder == null)
                {
                    continue;
                }

                AnimateItem(item, rootBorder);
            }
        }

        #endregion

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

        #region 항목 애니메이션 처리하기 - AnimateItem(item, rootBorder)

        /// <summary>
        /// 항목 애니메이션 처리하기
        /// </summary>
        /// <param name="item">리스트 박스 항목</param>
        /// <param name="rootBorder">루트 Border</param>
        private void AnimateItem(ListBoxItem item, Border rootBorder)
        {
            Thickness thickness;

            if(item.IsSelected)
            {
                ListBoxItemSlideDirection direction = this.SlideDirection;

                if(direction == ListBoxItemSlideDirection.Up)
                {
                    thickness = new Thickness(2, 0, 0, this.SlideDistance);
                }
                else if(direction == ListBoxItemSlideDirection.Right)
                {
                    thickness = new Thickness(2 + this.SlideDistance, 0, 0, 0);
                }
                else if(direction == ListBoxItemSlideDirection.Down)
                {
                    thickness = new Thickness(2, this.SlideDistance, 0, 0);
                }
                else
                {
                    thickness = new Thickness(2, 0, this.SlideDistance, 0);
                }
            }
            else
            {
               thickness = new Thickness(2, 0, 0, 0);
            }

            TimeSpan timeSpan = TimeSpan.FromMilliseconds(this.SlideDuration);

            Duration duration = new Duration(timeSpan);

            ThicknessAnimation animation = new ThicknessAnimation(thickness, duration);

            rootBorder.BeginAnimation(Border.PaddingProperty, animation);
        }

        #endregion 
    }
}

 

300x250

 

▶ 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="ListBox 클래스 : 항목 선택시 슬라이딩 리스트 박스 사용하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Window.Resources>
        <LinearGradientBrush x:Key="BackgroundLinearGradientBrushKey"
            StartPoint="0.5 0"
            EndPoint="0.5 1">
            <GradientStop Offset="0" Color="#66000000" />
            <GradientStop Offset="1" Color="#33000000" />
        </LinearGradientBrush>
        <Style x:Key="BorderStyleKey" TargetType="{x:Type Border}">
            <Setter Property="Margin"          Value="4"     />
            <Setter Property="BorderThickness" Value="0.5"   />
            <Setter Property="BorderBrush"     Value="Black" />
            <Setter Property="CornerRadius"    Value="4"     />
            <Setter Property="Background"      Value="{StaticResource BackgroundLinearGradientBrushKey}" />
            <Setter Property="Padding"         Value="4"     />
        </Style>
        <DataTemplate x:Key="SlidingHorizontalItemTemplateKey">
            <Border
                Style="{StaticResource BorderStyleKey}"
                Width="200">
                <TextBlock Text="{Binding}" />
            </Border>
        </DataTemplate>
        <DataTemplate x:Key="SlidingDownItemTemplateKey">
            <Rectangle
                Margin="8 0"
                Height="20"
                Width="55"
                Fill="{Binding}" />
        </DataTemplate>
        <DataTemplate x:Key="SlidingUpItemTemplateKey">
            <TextBlock
                Margin="8 0"
                Width="55"
                Background="{StaticResource BackgroundLinearGradientBrushKey}"
                Padding="6"
                TextAlignment="Center"
                Text="{Binding}" />
        </DataTemplate>    
    </Window.Resources>
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="100" />
            <RowDefinition Height="10"  />
            <RowDefinition Height="*"   />
            <RowDefinition Height="10"  />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"  />
            <ColumnDefinition Width="10" />
            <ColumnDefinition Width="*"  />
        </Grid.ColumnDefinitions>
        <local:SlidingListBox x:Name="listBox1" Grid.Row="0" Grid.ColumnSpan="3"
            ItemTemplate="{StaticResource SlidingDownItemTemplateKey}"
            SelectionMode="Extended"
            SlideDirection="Down"
            SlideDistance="60"
            SlideDuration="100"
            VerticalContentAlignment="Top">
            <local:SlidingListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel
                        Orientation="Horizontal"
                        IsItemsHost="True" />
                </ItemsPanelTemplate>
            </local:SlidingListBox.ItemsPanel>
        </local:SlidingListBox>
        <local:SlidingListBox x:Name="listBox2" Grid.Row="2" Grid.Column="0"
            ItemTemplate="{StaticResource SlidingHorizontalItemTemplateKey}"
            SelectionMode="Extended"
            SlideDirection="Right"
            SlideDistance="70"
            SlideDuration="90"
            HorizontalContentAlignment="Left" />
        <local:SlidingListBox x:Name="listBox3" Grid.Row="2" Grid.Column="2"
            ItemTemplate="{StaticResource SlidingHorizontalItemTemplateKey}"
            SelectionMode="Extended"
            SlideDirection="Left"
            SlideDistance="50"
            SlideDuration="200"
            HorizontalContentAlignment="Right" />
        <local:SlidingListBox x:Name="listBox4" Grid.Row="4" Grid.ColumnSpan="3"
            ItemTemplate="{StaticResource SlidingUpItemTemplateKey}"
            SelectionMode="Extended"
            SlideDirection="Up"
            SlideDistance="60"
            SlideDuration="100"
            VerticalContentAlignment="Bottom">
            <local:SlidingListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel
                        Orientation="Horizontal"
                        IsItemsHost="True" />
                </ItemsPanelTemplate>
            </local:SlidingListBox.ItemsPanel>
        </local:SlidingListBox>
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.Windows;
using System.Windows.Media;

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

        #region 생성자 - MainWindow()

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

            Loaded += Window_Loaded;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

        /// <summary>
        /// 윈도우 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Brush[] brusheArray = new SolidColorBrush[8];

            for(int i = 0; i < 8; i++)
            {
                byte value = (byte)(255 / (i + 1) * i);

                Color color = Color.FromRgb( value, value, value );

                brusheArray[i] = new SolidColorBrush(color);
            }

            this.listBox1.ItemsSource = brusheArray;

            this.listBox2.ItemsSource = new string[]
            {
                "Argentina",
                "Brooklyn",
                "Cambodia",
                "Denmark",
                "England",
                "Fairfield",
                "Germany",
                "Hamburg",
                "Indonesia",
            };

            this.listBox3.ItemsSource = new string[]
            {
                "Once",
                "Upon",
                "A",
                "Time",
                "There",
                "Were",
                "These",
                "Things",
                "Called",
                "HWNDs..."
            };

            this.listBox4.ItemsSource = new int[]
            {
                123,
                234,
                345,
                456,
                567,
                678,
                789
            };
        }

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

댓글을 달아 주세요