본문 바로가기
개발의 기록/Etc..

WPF Custom TextBox Control

by prographer J 2012. 1. 18.
728x90
WPF로 프로젝트를 하면서 참 많은 것을 만들었다. 그중 가장 쓸모가 있을 법한 내용을 소개한다.
이름하여 Custom Textbox! 어떤것인고 하니, Default String이 있고 이 Default String은 값이 Null일때만 나타난다.
그리고 TextBox에 Focus가 가면 그 내용이 사라지는 컨트롤이다. 

개발자는 코드만 보면 되는법!!


우선 Textbox를 상속받는 클래스를 하나 만든다.

public class CTextBox : TextBox

그리고 상속받은 클래스에 DependencyProperty를 추가해 준다. 이 내용은 DesignTime에서 내용을 주고 받기 위해서 만든다.

//기본 스트링 표시 Null일때 보여지는 문자
public static readonly DependencyProperty DefaultStringProperty = DependencyProperty.Register("DefaultString", typeof(string), typeof(CTextBox),
            new FrameworkPropertyMetadata("", CTextBoxPropertyChanged));

//기본 스트링의 문자 색 Null일때 보여지는 문자의 색
public static readonly DependencyProperty DefaultForegroundProperty = DependencyProperty.Register("DefaultForeground", typeof(Brush), typeof(CTextBox),
            new FrameworkPropertyMetadata(Brushes.Black, CTextBoxPropertyChanged));

//DefaultString Property 
public string DefaultString
{
get { return (string)GetValue(DefaultStringProperty); }
set { SetValue(DefaultStringProperty, value); }
}
//DefaultForeground Property
public Brush DefaultForeground
{
get { return (Brush)GetValue(DefaultForegroundProperty); }
set { SetValue(DefaultForegroundProperty, value); }
}
//Event
static void CTextBoxPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
(obj as CTextBox).CTextBoxPropertyChanged(args);
}
void CTextBoxPropertyChanged(DependencyPropertyChangedEventArgs args)
{

여기서 이 컨트롤에는 하나 더 추가 기능이 있다.바로~! Focus가 발생하면 기본문자열은 없에주고, Textbox에 데이터가 있다면 
전체 선택해 주는 기능이다.
그 기능을 위해 생성자에 이벤트를 생성해 준다.

public CTextBox()
{
AddHandler(PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(SelectivelyIgnoreMouseButton), true);
AddHandler(GotKeyboardFocusEvent,
new RoutedEventHandler(SelectAllText), true);
AddHandler(MouseDoubleClickEvent,
new RoutedEventHandler(SelectAllText), true);
AddHandler(LostKeyboardFocusEvent,
new RoutedEventHandler(SetDefaultText), true);
}

//마우스가 클릭 되기전 발생하는 이벤트
private void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
{
DependencyObject parent = e.OriginalSource as UIElement;
while (parent != null && !(parent is TextBox))
parent = VisualTreeHelper.GetParent(parent);

if (parent != null)
{
var textBox = (TextBox)parent;
if (!textBox.IsKeyboardFocusWithin)
{
//텍스트 박스를 검사하여 기본 문자열과 같을 경우 
if (textBox.Text == DefaultString)
{
textBox.Foreground = Brushes.Black;//글자색을 검정색으로 바꾸고
textBox.Text = "";//텍스트의 내용을 다 지워라
}
textBox.Focus();
e.Handled = true;
}
}
}

private void SetDefaultText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;
if (textBox.Text == "")//텍스트 박스의 데이터가 없을 경우
{
textBox.Text = DefaultString;//기본 텍스트로 변경
textBox.Foreground = DefaultForeground;
}
}

private void SelectAllText(object sender, RoutedEventArgs e)
{
var textBox = e.OriginalSource as TextBox;

if (textBox != null)
{
if (textBox.Text == DefaultString)
{
textBox.Foreground = Brushes.Black;
textBox.Text = "";
}
textBox.SelectAll();
}
}


모든 코드를 모와보면

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace CommonControl
{
    public class CTextBox : TextBox
    {

        public CTextBox()
        {
            AddHandler(PreviewMouseLeftButtonDownEvent,
                new MouseButtonEventHandler(SelectivelyIgnoreMouseButton), true);
            AddHandler(GotKeyboardFocusEvent,
                new RoutedEventHandler(SelectAllText), true);
            AddHandler(MouseDoubleClickEvent,
                new RoutedEventHandler(SelectAllText), true);
            AddHandler(LostKeyboardFocusEvent,
                new RoutedEventHandler(SetDefaultText), true);
        }


        public static readonly DependencyProperty DefaultStringProperty = DependencyProperty.Register("DefaultString", typeof(string), typeof(CTextBox),
            new FrameworkPropertyMetadata("", CTextBoxPropertyChanged));

        public static readonly DependencyProperty DefaultForegroundProperty = DependencyProperty.Register("DefaultForeground", typeof(Brush), typeof(CTextBox),
            new FrameworkPropertyMetadata(Brushes.Black, CTextBoxPropertyChanged));
        public string DefaultString
        {
            get { return (string)GetValue(DefaultStringProperty); }
            set { SetValue(DefaultStringProperty, value); }
        }
        public Brush DefaultForeground
        {
            get { return (Brush)GetValue(DefaultForegroundProperty); }
            set { SetValue(DefaultForegroundProperty, value); }
        }
        static void CTextBoxPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            (obj as CTextBox).CTextBoxPropertyChanged(args);
        }
        void CTextBoxPropertyChanged(DependencyPropertyChangedEventArgs args)
        {
            
        }
        

        private void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e)
        {
            DependencyObject parent = e.OriginalSource as UIElement;
            while (parent != null && !(parent is TextBox))
                parent = VisualTreeHelper.GetParent(parent);

            if (parent != null)
            {
                var textBox = (TextBox)parent;
                if (!textBox.IsKeyboardFocusWithin)
                {
                    if (textBox.Text == DefaultString)
                    {
                        textBox.Foreground = Brushes.Black;
                        textBox.Text = "";
                    }
                    textBox.Focus();
                    e.Handled = true;
                }
            }
        }

        private void SetDefaultText(object sender, RoutedEventArgs e)
        {
            var textBox = e.OriginalSource as TextBox;
            if (textBox.Text == "")
            {
                textBox.Text = DefaultString;
                textBox.Foreground = DefaultForeground;
            }
        }

        private void SelectAllText(object sender, RoutedEventArgs e)
        {
            var textBox = e.OriginalSource as TextBox;

            if (textBox != null)
            {
                if (textBox.Text == DefaultString)
                {
                    textBox.Foreground = Brushes.Black;
                    textBox.Text = "";
                }
                textBox.SelectAll();
            }
        }
    }
}

728x90

댓글