这一个让我难住。我发现一些code posted by Ray Burns为TextBox创建DependencyProperty,允许您限制用户可以删除哪些字符。我对其进行了一些修改,以限制插入的哪些字符可以插入,并用它来创建仅接受数字输入(加上小数点)的文本框。WPF中的TextBox.Text属性的奇怪情况
这很适合通过键盘输入文本,粘贴,拖放等。唯一的问题是通过代码设置文本时出现的问题。在那里它允许输入非数字文本,这本身并不是真正的问题。问题是,如果您在完成后检查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="."></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的Text属性是一个空字符串(即使它具有在UI中清晰可见的文本)。如果您以任何方式修改UI中的文本(例如删除一个字符),然后单击检查值,它现在会识别正确的文本。
任何人都可以阐明为什么发生这种情况?我可能会错过显而易见的东西,但我似乎无法弄清楚。
在此先感谢!
杰夫
感谢您的回复,Rob!不幸的是,添加该行代码后行为没有改变。 – JTennessen 2010-09-09 14:37:16
Rob,我意识到这让我花了不可思议的时间来回答这个问题,但我终于有机会在VS2010中使用.NET 4进行尝试了,而且我也和你一样。显然,不管是什么原因导致这个问题已经在.NET 4中改变了。感谢您的提示! – JTennessen 2012-04-11 22:02:22