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

■ ContentControl 클래스 : 리스트 컨트롤 만들기

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

using System;

using System.Collections;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

 

/// <summary>

/// 리스트 컨트롤

/// </summary>

public class ListControl : ContentControl

{

    //////////////////////////////////////////////////////////////////////////////////////////////////// Declaration

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

 

    #region Event

 

    /// <summary>

    /// 선택 변경시

    /// </summary>

    public event EventHandler SelectionChanged;

 

    #endregion

 

    //////////////////////////////////////////////////////////////////////////////////////////////////// Field

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

 

    #region Field

 

    /// <summary>

    /// 스크롤 뷰어

    /// </summary>

    private ScrollViewer scrollViewer;

 

    /// <summary>

    /// 스택 패널

    /// </summary>

    private StackPanel stackPanel;

 

    /// <summary>

    /// 배열 리스트

    /// </summary>

    private ArrayList arrayList = new ArrayList();

 

    /// <summary>

    /// 선택 인덱스

    /// </summary>

    private int selectedIndex = -1;

 

    #endregion

 

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

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

 

    #region 수 - Count

 

    /// <summary>

    ///

    /// </summary>

    public int Count

    {

        get

        {

            return this.arrayList.Count;

        }

    }

 

    #endregion

 

    #region 선택 인덱스 - SelectedIndex

 

    /// <summary>

    /// 선택 인덱스

    /// </summary>

    public int SelectedIndex

    {

        set

        {

            if(value < -1 || value >= Count)

            {

                throw new ArgumentOutOfRangeException("SelectedIndex");

            }

 

            if(value == this.selectedIndex)

            {

                return;

            }

 

            if(this.selectedIndex != -1)

            {

                TextBlock textBlock = this.stackPanel.Children[this.selectedIndex] as TextBlock;

 

                textBlock.Background = SystemColors.WindowBrush;

                textBlock.Foreground = SystemColors.WindowTextBrush;

            }

 

            this.selectedIndex = value;

 

            if(this.selectedIndex > -1)

            {

                TextBlock textBlock = this.stackPanel.Children[this.selectedIndex] as TextBlock;

 

                textBlock.Background = SystemColors.HighlightBrush;

                textBlock.Foreground = SystemColors.HighlightTextBrush;

            }

 

            ScrollIntoView();

 

            OnSelectionChanged(EventArgs.Empty);

        }

        get

        {

            return this.selectedIndex;

        }

    }

 

    #endregion

 

    #region 선택 항목 - SelectedItem

 

    /// <summary>

    /// 선택 항목

    /// </summary>

    public object SelectedItem

    {

        set

        {

            SelectedIndex = this.arrayList.IndexOf(value);

        }

        get

        {

            if(SelectedIndex > -1)

            {

                return this.arrayList[SelectedIndex];

            }

 

            return null;

        }

    }

 

    #endregion

 

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

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

 

    #region 생성자 - ListControl()

 

    /// <summary>

    /// 생성자

    /// </summary>

    public ListControl()

    {

        Focusable = false;

 

        Border border = new Border();

 

        border.BorderThickness = new Thickness(1);

        border.BorderBrush     = SystemColors.ActiveBorderBrush;

        border.Background      = SystemColors.WindowBrush;

 

        Content = border;

 

        this.scrollViewer = new ScrollViewer();

 

        this.scrollViewer.Focusable = false;

        this.scrollViewer.Padding   = new Thickness(2, 0, 0, 0);

 

        border.Child = this.scrollViewer;

 

        this.stackPanel = new StackPanel();

 

        this.scrollViewer.Content = this.stackPanel;

 

        AddHandler

        (

            TextBlock.MouseLeftButtonDownEvent,

            new MouseButtonEventHandler(textBlock_MouseLeftButtonDown)

        );

 

        Loaded += ListControl_Loaded;

    }

 

    #endregion

 

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

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

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

 

    #region 지우기 - Clear()

 

    /// <summary>

    /// 지우기

    /// </summary>

    public void Clear()

    {

        SelectedIndex = -1;

 

        this.stackPanel.Children.Clear();

 

        this.arrayList.Clear();

    }

 

    #endregion

 

    #region 추가하기 - Add(value)

 

    /// <summary>

    /// 추가하기

    /// </summary>

    /// <param name="value"></param>

    public void Add(object value)

    {

        this.arrayList.Add(value);

 

        TextBlock textBlock = new TextBlock();

 

        textBlock.Text = value.ToString();

 

        this.stackPanel.Children.Add(textBlock);

    }

 

    #endregion

 

    #region 삽입하기 - Insert(index, value)

 

    /// <summary>

    /// 삽입하기

    /// </summary>

    /// <param name="index">인덱스</param>

    /// <param name="value"></param>

    public void Insert(int index, object value)

    {

        this.arrayList.Insert(index, value);

 

        TextBlock textBlock = new TextBlock();

 

        textBlock.Text = value.ToString();

 

        this.stackPanel.Children.Add(textBlock);

    }

 

    #endregion

 

    #region 포함 여부 조사하기 - Contains(value)

 

    /// <summary>

    /// 포함 여부 조사하기

    /// </summary>

    /// <param name="value"></param>

    /// <returns>포함 여부</returns>

    public bool Contains(object value)

    {

        return this.arrayList.Contains(value);

    }

 

    #endregion

 

    #region 글자로 이동하기 - GoToLetter(character)

 

    /// <summary>

    /// 글자로 이동하기

    /// </summary>

    /// <param name="character">문자</param>

    public void GoToLetter(char character)

    {

        int offset = SelectedIndex + 1;

 

        for(int i = 0; i < Count; i++)

        {

            int index = (i + offset) % Count;

 

            if(Char.ToUpper(character) == Char.ToUpper(this.arrayList[index].ToString()[0]))

            {

                SelectedIndex = index;

 

                break;

            }

        }

    }

 

    #endregion

 

    #region 페이지 위로 이동하기 - PageUp()

 

    /// <summary>

    /// 페이지 위로 이동하기

    /// </summary>

    public void PageUp()

    {

        if(SelectedIndex == -1 || Count == 0)

        {

            return;

        }

 

        int index = SelectedIndex - (int)(Count * this.scrollViewer.ViewportHeight / this.scrollViewer.ExtentHeight);

 

        if(index < 0)

        {

            index = 0;

        }

 

        SelectedIndex = index;

    }

 

    #endregion

 

    #region 페이지 아래로 이동하기 - PageDown()

 

    /// <summary>

    /// 페이지 아래로 이동하기

    /// </summary>

    public void PageDown()

    {

        if(SelectedIndex == -1 || Count == 0)

        {

            return;

        }

 

        int index = SelectedIndex + (int)(Count * this.scrollViewer.ViewportHeight / this.scrollViewer.ExtentHeight);

 

        if(index > Count - 1)

        {

            index = Count - 1;

        }

 

        SelectedIndex = index;

    }

 

    #endregion

 

    #region 선택 항목 보이기 - ScrollIntoView()

 

    /// <summary>

    /// 선택 항목 보이기

    /// </summary>

    public void ScrollIntoView()

    {

        if(Count == 0 || SelectedIndex == -1 || this.scrollViewer.ViewportHeight > this.scrollViewer.ExtentHeight)

        {

            return;

        }

 

        double itemHeight       = this.scrollViewer.ExtentHeight / Count;

        double itemTopOffset    = SelectedIndex * itemHeight;

        double itemBottomOffset = (SelectedIndex + 1) * itemHeight;

 

        if(itemTopOffset < this.scrollViewer.VerticalOffset)

        {

            this.scrollViewer.ScrollToVerticalOffset(itemTopOffset);

        }

        else if(itemBottomOffset > this.scrollViewer.VerticalOffset + this.scrollViewer.ViewportHeight)

        {

            this.scrollViewer.ScrollToVerticalOffset

            (

                this.scrollViewer.VerticalOffset + itemBottomOffset - this.scrollViewer.VerticalOffset - this.scrollViewer.ViewportHeight

            );

        }

    }

 

    #endregion

 

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

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

 

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

 

    /// <summary>

    /// 선택 변경시 처리하기

    /// </summary>

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

    protected virtual void OnSelectionChanged(EventArgs e)

    {

        if(SelectionChanged != null)

        {

            SelectionChanged(this, e);

        }

    }

 

    #endregion

 

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

    //////////////////////////////////////////////////////////////////////////////// Event

 

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

 

    /// <summary>

    /// 리스트 컨트롤 로드시 처리하기

    /// </summary>

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

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

    private void ListControl_Loaded(object sender, RoutedEventArgs e)

    {

        ScrollIntoView();

    }

 

    #endregion

 

    #region 텍스트 블럭 마우스 왼쪽 버튼 DOWN 처리하기 - textBlock_MouseLeftButtonDown(sender, e)

 

    /// <summary>

    /// 텍스트 블럭 마우스 왼쪽 버튼 DOWN 처리하기

    /// </summary>

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

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

    private void textBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

    {

        if(e.Source is TextBlock)

        {

            SelectedIndex = this.stackPanel.Children.IndexOf(e.Source as TextBlock);

        }

    }

 

    #endregion

}

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

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요