这个让我难过。我找到了一些code posted by Ray Burns来为TextBox创建DependencyProperty,允许您限制用户可以删除哪些字符。我修改了一下来改为限制哪些字符可以插入,并用它来创建只接受数字输入(加上小数点)的TextBox。
这非常适合通过键盘输入文本,粘贴,拖放等。唯一的问题是通过代码设置文本时。在那里它允许输入非数字文本,这本身并不是真正的问题。问题是,如果在执行此操作后检查TextBox的Text属性的值,则表示它是一个空字符串。
这里有一些代码来证明我的意思。一个简单的WPF窗口:
<Window x:Class="TestApp.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:TestApp"
Title="Test" Height="125" Width="200">
<Canvas>
<TextBox x:Name="txtTest" Canvas.Left="10" Canvas.Top="10" Width="100" my:TextBoxRestriction.RestrictInsertTo=".0123456789"></TextBox>
<Button Canvas.Left="10" Canvas.Top="40" Click="Button_Click">Enter Text</Button>
<Button Canvas.Left="75" Canvas.Top="40" Click="Button_Click_1">Check Value</Button>
</Canvas>
</Window>
它的代码隐藏:
using System;
using System.Windows;
namespace TestApp
{
public partial class Test : Window
{
public Test()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
txtTest.Text = "Test";
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MessageBox.Show(txtTest.Text, "Length = " + txtTest.Text.Length.ToString());
}
}
}
我修改雷的课程:
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace TestApp
{
//Based on code by Ray Burns at https://stackoverflow.com/questions/3051590/how-to-track-which-character-is-deleted-in-textbox-in-wpf/3056168#3056168.
public class TextBoxRestriction : DependencyObject
{
//RestrictInsertTo: Set this to the characters that may be inserted.
public static string GetRestrictInsertTo(DependencyObject obj)
{
return (string)obj.GetValue(RestrictInsertToProperty);
}
public static void SetRestrictInsertTo(DependencyObject obj, string value)
{
obj.SetValue(RestrictInsertToProperty, value);
}
public static readonly DependencyProperty RestrictInsertToProperty = DependencyProperty.RegisterAttached("RestrictInsertTo", typeof(string), typeof(TextBoxRestriction), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
var box = (TextBox)obj;
box.TextChanged += (obj2, changeEvent) =>
{
var oldText = GetUnrestrictedText(box);
var allowedChars = GetRestrictInsertTo(box);
if (box.Text == oldText || allowedChars == null) return;
foreach (var change in changeEvent.Changes)
{
if (change.AddedLength > 0)
{
string added = box.Text.Substring(change.Offset, change.AddedLength);
if (added.Any(ch => !allowedChars.Contains(ch)))
{
var ss = box.SelectionStart;
var sl = box.SelectionLength;
box.Text = oldText;
box.SelectionStart = ss;
box.SelectionLength = sl;
}
}
}
SetUnrestrictedText(box, box.Text);
};
}
});
//UnrestrictedText: Bind or access this property to update the Text property bypassing all restrictions.
public static string GetUnrestrictedText(DependencyObject obj)
{
return (string)obj.GetValue(UnrestrictedTextProperty);
}
public static void SetUnrestrictedText(DependencyObject obj, string value)
{
obj.SetValue(UnrestrictedTextProperty, value);
}
public static readonly DependencyProperty UnrestrictedTextProperty = DependencyProperty.RegisterAttached("UnrestrictedText", typeof(string), typeof(TextBoxRestriction), new PropertyMetadata
{
DefaultValue = "",
PropertyChangedCallback = (obj, e) =>
{
var box = (TextBox)obj;
box.Text = (string)e.NewValue;
}
});
}
}
如果您尝试键入TextBox,您会看到它的工作方式与预期相同,并且单击“检查值”按钮可以准确地反映文本;但是,如果单击“输入文本”按钮,然后单击“检查值”按钮,您将看到应用程序认为TextBox的Text属性为空字符串(即使UI中的文本清晰可见)。如果以任何方式修改UI中的文本(例如删除一个字符),然后单击“检查值”,它现在可以识别正确的文本。
任何人都可以解释为什么会这样吗?我可能会遗漏一些显而易见的东西,但我似乎无法弄明白。
提前致谢!
杰夫
答案 0 :(得分:2)
我认为您还需要在obj.SetValue(TextProperty, value)
方法中执行SetUnrestrictedText
。 击>
这是第一个猜测。如果不是这样的话,我会更深入地研究它,没有其他人回复。
我尝试使用我的机器上的示例代码VS2010,.NET 4.附加属性每次都会重置TextBox
的Text属性。我尝试了几种无效输入的变种。
如果你想要的是DependencyObject 过滤掉代码中的赋值,拒绝无效字符并保留有效字符,那么你需要一个不同于if (added.Any(ch => !allowedChars.Contains(ch)))
的测试。 / p>