728x90
반응형
728x170
▶ TextBoxInputMode.cs
namespace TestProject
{
/// <summary>
/// 텍스트 박스 입력 모드
/// </summary>
public enum TextBoxInputMode
{
/// <summary>
/// 해당 무
/// </summary>
None,
/// <summary>
/// 십진수 입력
/// </summary>
DecimalInput,
/// <summary>
/// 숫자 입력
/// </summary>
DigitInput
}
}
728x90
▶ TextBoxInputBehavior.cs
using System;
using System.Globalization;
using System.Linq;
using System.Media;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace TestProject
{
/// <summary>
/// 텍스트 박스 입력 동작
/// </summary>
public class TextBoxInputBehavior : Behavior<TextBox>
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Public
#region 양수만 십진수 입력 여부 속성 - JustPositivDecimalInputProperty
/// <summary>
/// 양수만 십진수 입력 여부 속성
/// </summary>
public static readonly DependencyProperty JustPositivDecimalInputProperty = DependencyProperty.Register
(
"JustPositivDecimalInput",
typeof(bool),
typeof(TextBoxInputBehavior),
new FrameworkPropertyMetadata(false)
);
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 유효 숫자 스타일
/// </summary>
private const NumberStyles validNumberStyles = NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 입력 모드 - InputMode
/// <summary>
/// 입력 모드
/// </summary>
public TextBoxInputMode InputMode { get; set; }
#endregion
#region 양수만 십진수 입력 여부 - JustPositivDecimalInput
/// <summary>
/// 양수만 십진수 입력 여부
/// </summary>
public bool JustPositivDecimalInput
{
get
{
return (bool)GetValue(JustPositivDecimalInputProperty);
}
set
{
SetValue(JustPositivDecimalInputProperty, value);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - TextBoxInputBehavior()
/// <summary>
/// 생성자
/// </summary>
public TextBoxInputBehavior()
{
InputMode = TextBoxInputMode.None;
JustPositivDecimalInput = false;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 부착시 처리하기 - OnAttached()
/// <summary>
/// 부착시 처리하기
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown;
AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
DataObject.AddPastingHandler(AssociatedObject, AssociatedObject_Pasting);
}
#endregion
#region 탈착시 처리하기 - OnDetaching()
/// <summary>
/// 탈착시 처리하기
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewKeyDown -= AssociatedObject_PreviewKeyDown;
AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput;
DataObject.RemovePastingHandler(AssociatedObject, AssociatedObject_Pasting);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 관련 객체 프리뷰 키 DOWN 처리하기 - AssociatedObject_PreviewKeyDown(sender, e)
/// <summary>
/// 관련 객체 프리뷰 키 DOWN 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Space)
{
if(!IsValidInput(GetText(" ")))
{
SystemSounds.Beep.Play();
e.Handled = true;
}
}
}
#endregion
#region 관련 객체 프리뷰 텍스트 입력시 처리하기 - AssociatedObject_PreviewTextInput(sender, e)
/// <summary>
/// 관련 객체 프리뷰 텍스트 입력시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void AssociatedObject_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if(!IsValidInput(GetText(e.Text)))
{
SystemSounds.Beep.Play();
e.Handled = true;
}
}
#endregion
#region 관련 객체 붙여넣기시 처리하기 - AssociatedObject_Pasting(sender, e)
/// <summary>
/// 관련 객체 붙여넣기시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void AssociatedObject_Pasting(object sender, DataObjectPastingEventArgs e)
{
if(e.DataObject.GetDataPresent(typeof(string)))
{
string text = (string)e.DataObject.GetData(typeof(string));
if(!IsValidInput(GetText(text)))
{
SystemSounds.Beep.Play();
e.CancelCommand();
}
}
else
{
SystemSounds.Beep.Play();
e.CancelCommand();
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 텍스트 구하기 - GetText(source)
/// <summary>
/// 텍스트 구하기
/// </summary>
/// <param name="source">소스 문자열</param>
/// <returns>텍스트</returns>
private string GetText(string source)
{
TextBox textBox = AssociatedObject;
int selectionStart = textBox.SelectionStart;
if(textBox.Text.Length < selectionStart)
{
selectionStart = textBox.Text.Length;
}
int selectionLength = textBox.SelectionLength;
if(textBox.Text.Length < selectionStart + selectionLength)
{
selectionLength = textBox.Text.Length - selectionStart;
}
string actualText = textBox.Text.Remove(selectionStart, selectionLength);
int caretIndex = textBox.CaretIndex;
if(actualText.Length < caretIndex)
{
caretIndex = actualText.Length;
}
string target = actualText.Insert(caretIndex, source);
return target;
}
#endregion
#region 숫자 여부 구하기 - IsDigit(source)
/// <summary>
/// 숫자 여부 구하기
/// </summary>
/// <param name="source">소스 문자열</param>
/// <returns>숫자 여부</returns>
private bool IsDigit(string source)
{
return source.ToCharArray().All(Char.IsDigit);
}
#endregion
#region 유효 입력 여부 구하기 - IsValidInput(source)
/// <summary>
/// 유효 입력 여부 구하기
/// </summary>
/// <param name="source">소스 문자열</param>
/// <returns>유효 입력 여부</returns>
private bool IsValidInput(string source)
{
switch(InputMode)
{
case TextBoxInputMode.None :
return true;
case TextBoxInputMode.DigitInput :
return IsDigit(source);
case TextBoxInputMode.DecimalInput :
decimal decimalValue;
if(source.ToCharArray().Where(x => x == '.').Count() > 1)
{
return false;
}
if(source.Contains("-"))
{
if(JustPositivDecimalInput)
{
return false;
}
if(source.IndexOf("-", StringComparison.Ordinal) > 0)
{
return false;
}
if(source.ToCharArray().Count(x=> x == '-') > 1)
{
return false;
}
if(source.Length == 1)
{
return true;
}
}
bool result = decimal.TryParse(source, validNumberStyles, CultureInfo.CurrentCulture, out decimalValue);
return result;
default :
throw new ArgumentException("Unknown TextBoxInputMode");
}
}
#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:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:TestProject"
Width="800"
Height="600"
Title="Behavior<T> 클래스 : 숫자 입력 텍스트 박스 동작 사용하기"
FontFamily="나눔고딕코딩"
FontSize="16">
<Grid>
<TextBox
Width="200"
Height="25"
HorizontalContentAlignment="Right"
VerticalContentAlignment="Center">
<i:Interaction.Behaviors>
<local:TextBoxInputBehavior InputMode="DecimalInput" />
</i:Interaction.Behaviors>
</TextBox>
</Grid>
</Window>
728x90
반응형
그리드형(광고전용)
'C# > WPF' 카테고리의 다른 글
[C#/WPF] RoutedCommand 클래스 : 커스텀 라우팅 명령 사용하기 (0) | 2020.09.15 |
---|---|
[C#/WPF] CommandManager 클래스 : AddExecutedHandler/AddCanExecuteHandler 메소드를 사용해 명령 핸들러 추가/제거하기 (0) | 2020.09.15 |
[C#/WPF] RoutedCommand 클래스 : 커스텀 라우팅 명령 사용하기 (0) | 2020.09.15 |
[C#/WPF] Button 엘리먼트 : CommandTarget 속성 사용하기 (0) | 2020.09.15 |
[C#/WPF] KeyBinding 클래스 : 단축키 사용하기 (0) | 2020.09.15 |
[C#/WPF] TextBox 클래스 : PreviewTextInput 이벤트를 사용해 3자리마다 콤마를 갖는 숫자 입력하기 (0) | 2020.09.14 |
[C#/WPF] LogicalTreeHelper 클래스 : FindLogicalNode 정적 메소드를 사용해 엘리먼트 찾기 (0) | 2020.09.14 |
[C#/WPF] CollectionViewSource 엘리먼트 : Source 속성 사용하기 (0) | 2020.09.14 |
[C#/WPF] BindingOperations 클래스 : ClearBinding/SetBinding 정적 메소드를 사용해 바인딩하기 (0) | 2020.09.14 |
[C#/WPF] Grid 클래스 : 자동 인덱스 설정 그리드 사용하기 (0) | 2020.09.13 |
댓글을 달아 주세요