2010-10-11 7 views
5

Dans mon application WPF, j'ai un TextBox où l'utilisateur peut entrer un pourcentage (int, entre 1 et 100). La propriété Text est databound à une propriété dans un ViewModel, où je force la valeur à être dans la plage donnée dans le setter.Coercition d'un TextBox WPF ne fonctionne plus dans .NET 4.0

Toutefois, dans .NET 3.5, les données ne s'affichent pas correctement dans l'interface utilisateur après avoir été forcées. Dans this post on MSDN, Dr. WPF indique que vous devez mettre à jour manuellement la liaison pour que le correct soit affiché. Par conséquent, j'ai un gestionnaire TextChanged (dans la vue) qui appelle UpdateTarget(). Dans le code:

Voir XAML:

<TextBox Text="{Binding Percentage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, TargetNullValue={x:Static sys:String.Empty}}" 
    TextChanged="TextBox_TextChanged"/> 

Voir codebehind:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
{ 
    // Removed safe casts and null checks 
    ((TextBox)sender).GetBindingExpression(TextBox.TextProperty).UpdateTarget(); 
} 

ViewModel:

private int? percentage; 
public int? Percentage 
{ 
    get 
    { 
     return this.percentage; 
    } 

    set 
    { 
     if (this.Percentage == value) 
     { 
      return; 
     } 

     // Unset = 1 
     this.percentage = value ?? 1; 

     // Coerce to be between 1 and 100. 
     // Using the TextBox, a user may attempt setting a larger or smaller value. 
     if (this.Percentage < 1) 
     { 
      this.percentage = 1; 
     } 
     else if (this.Percentage > 100) 
     { 
      this.percentage = 100; 
     } 
     this.NotifyPropertyChanged("Percentage"); 
    } 
} 

Malheureusement, ce code casse dans .NET 4.0 (même code, simplement a changé TargetFramework en 4.0). Spécifiquement, après avoir forcé la valeur pour la première fois, le TextBox ignore toutes les autres valeurs forcées tant que je continue à entrer des valeurs entières (puisque je lie à un int). Donc, si j'entre "123", après le 3 je vois la valeur "100". Maintenant, si j'entre "4", le setter dans le ViewModel obtient la valeur "1004", qu'il contraint à 100. L'événement TextChanged se déclenche alors (et TextBox.Text de l'expéditeur est "100"!), Mais le TextBox montre " 1004 ". Si j'entre alors "5", le setter obtient la valeur "10045", etc.

Si j'entre alors un "a", le TextBox affiche soudainement la valeur correcte, c'est-à-dire "100". La même chose se produit si je continue à entrer des nombres jusqu'à ce que l'int déborde.

Comment puis-je résoudre ce problème?

Répondre

3

Essayez d'utiliser en XAML explicite au lieu de PropertyChanged:

<TextBox Text="{Binding Percentage, Mode=TwoWay, UpdateSourceTrigger=Explicit, TargetNullValue={x:Static System:String.Empty}}" 
      TextChanged="TextBox_TextChanged" /> 

et dans le code derrière UpdateSource au lieu de UpdateTarget

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     // Removed safe casts and null checks 
     ((TextBox)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
    } 

testé et il fonctionne. Btw ce problème sera probablement résolu dans une version ultérieure de .NET.

0

Vous pouvez utiliser PropertyChanged. Cependant, essayez de vous lier à la dépendance EditValueProperty au lieu de la dépendance TextProperty (ou des événements). Cela fonctionnera comme désiré.