숫자와 소수점을 허용하려고하지만 부호는 없습니다.
Windows Forms 용 NumericUpDown 컨트롤을 사용하는 샘플과 Microsoft의 NumericUpDown 사용자 지정 컨트롤 샘플을 살펴 보았습니다 . 그러나 지금까지 NumericUpDown (WPF에서 지원 여부)은 원하는 기능을 제공하지 않는 것처럼 보입니다. 내 응용 프로그램이 디자인 된 방식으로 올바른 마음을 가진 사람은 화살표를 엉망으로 만들지 않을 것입니다. 그들은 내 응용 프로그램의 맥락에서 실용적인 의미가 없습니다.
그래서 표준 WPF TextBox에서 원하는 문자 만 허용하는 간단한 방법을 찾고 있습니다. 이게 가능해? 실용적입니까?
답변
미리보기 텍스트 입력 이벤트를 추가하십시오. 그렇습니다 : <TextBox PreviewTextInput="PreviewTextInput" />
.
그런 다음 그 안에 e.Handled
텍스트가 허용되지 않는 경우 를 설정하십시오 .e.Handled = !IsTextAllowed(e.Text);
IsTextAllowed
방법에 간단한 정규식을 사용하여 입력 한 것을 허용 해야하는지 확인합니다. 제 경우에는 숫자, 점 및 대시 만 허용하고 싶습니다.
private static readonly Regex _regex = new Regex("[^0-9.-]+"); //regex that matches disallowed text
private static bool IsTextAllowed(string text)
{
return !_regex.IsMatch(text);
}
잘못된 데이터를 붙여 넣지 않으려면 다음 과 같이 DataObject.Pasting
이벤트 DataObject.Pasting="TextBoxPasting"
를 연결 하십시오 (코드 발췌).
// Use the DataObject.Pasting Handler
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
String text = (String)e.DataObject.GetData(typeof(String));
if (!IsTextAllowed(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
답변
이벤트 핸들러가 텍스트 입력을 미리보고 있습니다. 여기서 정규식은 숫자가 아닌 경우에만 텍스트 입력과 일치하며 입력 텍스트 상자에 입력되지 않습니다.
문자 만 원하면 정규식을로 바꾸십시오 [^a-zA-Z]
.
XAML
<TextBox Name="NumberTextBox" PreviewTextInput="NumberValidationTextBox"/>
XAML.CS 파일
using System.Text.RegularExpressions;
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
{
Regex regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}
답변
나는 이미 여기에있는 것들 중 일부를 사용했고 행동을 사용하여 내 자신의 비틀기를 넣었으므로 많은 코드를 통해이 코드를 전파 할 필요가 없습니다 …
public class AllowableCharactersTextBoxBehavior : Behavior<TextBox>
{
public static readonly DependencyProperty RegularExpressionProperty =
DependencyProperty.Register("RegularExpression", typeof(string), typeof(AllowableCharactersTextBoxBehavior),
new FrameworkPropertyMetadata(".*"));
public string RegularExpression
{
get
{
return (string)base.GetValue(RegularExpressionProperty);
}
set
{
base.SetValue(RegularExpressionProperty, value);
}
}
public static readonly DependencyProperty MaxLengthProperty =
DependencyProperty.Register("MaxLength", typeof(int), typeof(AllowableCharactersTextBoxBehavior),
new FrameworkPropertyMetadata(int.MinValue));
public int MaxLength
{
get
{
return (int)base.GetValue(MaxLengthProperty);
}
set
{
base.SetValue(MaxLengthProperty, value);
}
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewTextInput += OnPreviewTextInput;
DataObject.AddPastingHandler(AssociatedObject, OnPaste);
}
private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(DataFormats.Text))
{
string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));
if (!IsValid(text, true))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
}
void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = !IsValid(e.Text, false);
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewTextInput -= OnPreviewTextInput;
DataObject.RemovePastingHandler(AssociatedObject, OnPaste);
}
private bool IsValid(string newText, bool paste)
{
return !ExceedsMaxLength(newText, paste) && Regex.IsMatch(newText, RegularExpression);
}
private bool ExceedsMaxLength(string newText, bool paste)
{
if (MaxLength == 0) return false;
return LengthOfModifiedText(newText, paste) > MaxLength;
}
private int LengthOfModifiedText(string newText, bool paste)
{
var countOfSelectedChars = this.AssociatedObject.SelectedText.Length;
var caretIndex = this.AssociatedObject.CaretIndex;
string text = this.AssociatedObject.Text;
if (countOfSelectedChars > 0 || paste)
{
text = text.Remove(caretIndex, countOfSelectedChars);
return text.Length + newText.Length;
}
else
{
var insert = Keyboard.IsKeyToggled(Key.Insert);
return insert && caretIndex < text.Length ? text.Length : text.Length + newText.Length;
}
}
}
관련 뷰 코드는 다음과 같습니다.
<TextBox MaxLength="50" TextWrapping="Wrap" MaxWidth="150" Margin="4"
Text="{Binding Path=FileNameToPublish}" >
<interactivity:Interaction.Behaviors>
<v:AllowableCharactersTextBoxBehavior RegularExpression="^[0-9.\-]+$" MaxLength="50" />
</interactivity:Interaction.Behaviors>
</TextBox>
답변
이것은 WilP 의 답변을 개선 한 솔루션입니다 . 내 개선 사항은 다음과 같습니다
- Del 및 Backspace 버튼의 동작 개선
EmptyValue
빈 문자열이 부적절한 경우 속성 추가- 사소한 오타 수정
/// <summary>
/// Regular expression for Textbox with properties:
/// <see cref="RegularExpression"/>,
/// <see cref="MaxLength"/>,
/// <see cref="EmptyValue"/>.
/// </summary>
public class TextBoxInputRegExBehaviour : Behavior<TextBox>
{
#region DependencyProperties
public static readonly DependencyProperty RegularExpressionProperty =
DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxInputRegExBehaviour), new FrameworkPropertyMetadata(".*"));
public string RegularExpression
{
get { return (string)GetValue(RegularExpressionProperty); }
set { SetValue(RegularExpressionProperty, value); }
}
public static readonly DependencyProperty MaxLengthProperty =
DependencyProperty.Register("MaxLength", typeof(int), typeof(TextBoxInputRegExBehaviour),
new FrameworkPropertyMetadata(int.MinValue));
public int MaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
set { SetValue(MaxLengthProperty, value); }
}
public static readonly DependencyProperty EmptyValueProperty =
DependencyProperty.Register("EmptyValue", typeof(string), typeof(TextBoxInputRegExBehaviour), null);
public string EmptyValue
{
get { return (string)GetValue(EmptyValueProperty); }
set { SetValue(EmptyValueProperty, value); }
}
#endregion
/// <summary>
/// Attach our behaviour. Add event handlers
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewTextInput += PreviewTextInputHandler;
AssociatedObject.PreviewKeyDown += PreviewKeyDownHandler;
DataObject.AddPastingHandler(AssociatedObject, PastingHandler);
}
/// <summary>
/// Deattach our behaviour. remove event handlers
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewTextInput -= PreviewTextInputHandler;
AssociatedObject.PreviewKeyDown -= PreviewKeyDownHandler;
DataObject.RemovePastingHandler(AssociatedObject, PastingHandler);
}
#region Event handlers [PRIVATE] --------------------------------------
void PreviewTextInputHandler(object sender, TextCompositionEventArgs e)
{
string text;
if (this.AssociatedObject.Text.Length < this.AssociatedObject.CaretIndex)
text = this.AssociatedObject.Text;
else
{
// Remaining text after removing selected text.
string remainingTextAfterRemoveSelection;
text = TreatSelectedText(out remainingTextAfterRemoveSelection)
? remainingTextAfterRemoveSelection.Insert(AssociatedObject.SelectionStart, e.Text)
: AssociatedObject.Text.Insert(this.AssociatedObject.CaretIndex, e.Text);
}
e.Handled = !ValidateText(text);
}
/// <summary>
/// PreviewKeyDown event handler
/// </summary>
void PreviewKeyDownHandler(object sender, KeyEventArgs e)
{
if (string.IsNullOrEmpty(this.EmptyValue))
return;
string text = null;
// Handle the Backspace key
if (e.Key == Key.Back)
{
if (!this.TreatSelectedText(out text))
{
if (AssociatedObject.SelectionStart > 0)
text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart - 1, 1);
}
}
// Handle the Delete key
else if (e.Key == Key.Delete)
{
// If text was selected, delete it
if (!this.TreatSelectedText(out text) && this.AssociatedObject.Text.Length > AssociatedObject.SelectionStart)
{
// Otherwise delete next symbol
text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, 1);
}
}
if (text == string.Empty)
{
this.AssociatedObject.Text = this.EmptyValue;
if (e.Key == Key.Back)
AssociatedObject.SelectionStart++;
e.Handled = true;
}
}
private void PastingHandler(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(DataFormats.Text))
{
string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));
if (!ValidateText(text))
e.CancelCommand();
}
else
e.CancelCommand();
}
#endregion Event handlers [PRIVATE] -----------------------------------
#region Auxiliary methods [PRIVATE] -----------------------------------
/// <summary>
/// Validate certain text by our regular expression and text length conditions
/// </summary>
/// <param name="text"> Text for validation </param>
/// <returns> True - valid, False - invalid </returns>
private bool ValidateText(string text)
{
return (new Regex(this.RegularExpression, RegexOptions.IgnoreCase)).IsMatch(text) && (MaxLength == int.MinValue || text.Length <= MaxLength);
}
/// <summary>
/// Handle text selection
/// </summary>
/// <returns>true if the character was successfully removed; otherwise, false. </returns>
private bool TreatSelectedText(out string text)
{
text = null;
if (AssociatedObject.SelectionLength <= 0)
return false;
var length = this.AssociatedObject.Text.Length;
if (AssociatedObject.SelectionStart >= length)
return true;
if (AssociatedObject.SelectionStart + AssociatedObject.SelectionLength >= length)
AssociatedObject.SelectionLength = length - AssociatedObject.SelectionStart;
text = this.AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength);
return true;
}
#endregion Auxiliary methods [PRIVATE] --------------------------------
}
사용법은 매우 간단합니다.
<i:Interaction.Behaviors>
<behaviours:TextBoxInputRegExBehaviour RegularExpression="^\d+$" MaxLength="9" EmptyValue="0" />
</i:Interaction.Behaviors>
답변
다음은 MVVM을 사용하여 매우 간단하고 쉬운 방법입니다.
텍스트 상자를 뷰 모델의 정수 속성과 바인딩하면 보석처럼 작동합니다. 텍스트 상자에 정수가 아닌 문자를 입력하면 유효성 검사가 표시됩니다.
XAML 코드 :
<TextBox x:Name="contactNoTxtBox" Text="{Binding contactNo}" />
모델 코드보기 :
private long _contactNo;
public long contactNo
{
get { return _contactNo; }
set
{
if (value == _contactNo)
return;
_contactNo = value;
OnPropertyChanged();
}
}
답변
텍스트가 변경 될 때 데이터가 숫자인지 여부를 확인하고 데이터가 숫자 인 경우 처리를 계속할 수 있는지 확인하고 그렇지 않은 경우 해당 필드에 숫자 데이터 만 허용하도록 사용자에게 프롬프트하도록 유효성 검사 규칙을 추가하십시오.