2013-03-06 40 views
1

有一个TextBox,我想限制输入范围。
在这个简单的例子Int32从0到300.
在现实生活中,范围更复杂,我不想让用户界面参与,除了接收和显示有效的值。TextBox Not Honoring值返回获取

如果我输入333,它会得到300和300的文本框。

这里的问题是:
然后,如果我添加一个数字为3001套分配的300
得到一个值调用,并返回300
但3001仍然是在文本框。

如果我粘贴3001,那么它正确显示300.
它只有当一个按键笔画使4(或更大)的数字,它失败。

<TextBox Text="{Binding Path=LimitInt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="60" Height="20"/> 

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    private Int32 limitInt = 0; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    public Int32 LimitInt 
    { 
     get { return limitInt; } 
     set 
     { 
      if (limitInt == value) return; 
      limitInt = value; 
      if (limitInt < 0) limitInt = 0; 
      if (limitInt > 300) limitInt = 300; 
      NotifyPropertyChanged("LimitInt"); 
     } 
    } 
} 
+1

您需要实现验证。看看[这篇博文](http://weblogs.asp.net/monikadyrda/archive/2009/06/24/wpf-textbox-validation.aspx)。 – 2013-03-06 19:18:44

+0

@MichaelPerrenoud假装我不想使用验证。为什么通过在UI中获取不是那个值来返回值? 301显示300. -1显示0.但3001显示3001. – Paparazzi 2013-03-06 19:28:43

+0

我没有得到同样的问题...我复制/粘贴你的代码,当我按'1'为'3001'时,它给了我'300'。 – 2013-03-06 20:08:21

回答

3

我相信会发生这种情况,因为您在绑定操作过程中正在更改绑定源的值。当您在绑定上使用UpdateSourceTrigger=PropertyChanged时,您告诉它在每次按键时重新评估。在这种情况下,Binding正在将该值推送给源,而不是试图通过从源拉取目标来更新目标。

即使在您提出您的NotifyPropertyChanged后,我想象因为您处于绑定操作的中间,目标不会被更新。

您可以通过删除UpdateSourceTrigger并将其保留为默认值(LostFocus)来解决此问题。只要您在用户选项卡出来之后熟悉它,这样做就可以工作。

<TextBox Text="{Binding Path=LimitInt}" Width="60" Height="20"/> 

(Mode = TwoWay是TextBox的默认值,所以您可以删除它)。

如果你想在每次按键时评估它,我会建议寻找蒙面编辑,并处理keypress/keydown,以防止值进入TextBox,而不是试图在他们'已经进入。

+0

的另一个原因我不同意你的说法,“不要试图通过从源代码来更新目标”。 Get被调用并返回适当的值。 -1正确显示为0. 301正确显示300.获取3001集合正确返回300,但UI不显示300. – Paparazzi 2013-03-06 19:54:37

+0

我没有调试框架代码,所以我在这里进行推测并努力解释清楚,但我并不是想说Source永远不会被取消 - NotifyPropertyChanged会强制它调用get - 但是在将新值推送到Source的过程中发生这种情况,而TextBox仍在处理文本输入。没有通过框架,我的猜测是,拉是否被目标放弃,因为它处于推送操作的中间,或者目标值在推送到源时被“锁定”。 – 2013-03-06 20:11:37

+0

谢谢。如果我使用LostFocus,它就可以工作。不是我想要的效果。我会按照Perrenoud的建议尝试验证。 +1 – Paparazzi 2013-03-06 20:33:29

1

这是一个更好的使用验证。

方法如下:

定义您的XAML来检查PreviewTextInput

<TextBox Text="{Binding Path=LimitInt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" PreviewTextInput="CheckNumberValidationHandler" Width="60" Height="20"/> 

然后设置您的验证处理程序:

/// <summary> 
/// Check to make sure the input is valid 
/// </summary> 
/// <param name="sender"></param> 
/// <param name="e"></param> 
private void CheckNumberValidationHandler(object sender, TextCompositionEventArgs e) { 
    if(IsTextAllowed(e.Text)) { 
    Int32 newVal; 
    newVal = Int32.Parse(LimitInt.ToString() + e.Text); 
    if(newVal < 0) { 
     LimitInt = 0; 
     e.Handled = true; 
    } 
    else if(newVal > 300) { 
     LimitInt = 300; 
     e.Handled = true; 
    } 
    else { 
     e.Handled = false; 
    } 
    } 
    else { 
    e.Handled = true; 
    } 
} 

/// <summary> 
/// Check if Text is allowed 
/// </summary> 
/// <param name="text"></param> 
/// <returns></returns> 
private static bool IsTextAllowed(string text) { 
    Regex regex = new Regex("[^0-9]+"); 
    return !regex.IsMatch(text); 
} 

编辑:我查了一下,和它的作品在.NET 4.0中:)

+0

我怀疑这是正确的,所以给它+1。但现在我正在与LostFocus合作。直到我测试它不能给它检查。 – Paparazzi 2013-03-07 02:11:33

+0

@Blam不用担心,它确实是一种更好的方法,因为使用'PreviewTextInput'可以防止输入值,而不是在赋值后进行检查。 – 2013-03-08 20:27:05