2010-10-11 10 views
5

In meiner WPF-Anwendung habe ich eine TextBox, wo der Benutzer einen Prozentsatz eingeben kann (als int, zwischen 1 und 100). Die Eigenschaft Text ist mit einer Eigenschaft in einem ViewModel verknüpft, wobei ich den Wert im Setter in dem angegebenen Bereich erzwinge.Coerce ein WPF TextBox funktioniert nicht mehr in .NET 4.0

In .NET 3.5 werden die Daten jedoch nicht ordnungsgemäß in der Benutzeroberfläche angezeigt, nachdem sie erzwungen wurden. In this post on MSDN, Dr. WPF sagt, dass Sie die Bindung manuell aktualisieren müssen, damit die richtige angezeigt wird. Daher habe ich einen TextChanged Handler (in der Ansicht), der UpdateTarget() aufruft. In Code:

anzeigen XAML:

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

anzeigen Code-Behind:

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

Ansichtsmodell:

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"); 
    } 
} 

Leider ist dieser Code bricht in .NET 4.0 (gleiche Code, einfach TargetFramework auf 4.0 geändert). Insbesondere, nachdem ich den Wert zum ersten Mal erzwungen habe, ignoriert das Textfeld alle weiteren erzwungenen Werte, solange ich fortfahre, ganzzahlige Werte einzugeben (da ich an einen int binde).

Also wenn ich "123" eingeben, nach der 3 sehe ich den Wert "100". Wenn ich nun "4" eintrage, erhält der Setter im ViewModel den Wert "1004", was er auf 100 erzwingt. Das TextChanged-Ereignis wird dann ausgelöst (und der TextBox.Text des Absenders ist "100"!), Aber die TextBox zeigt " 1004 ". Wenn ich dann "5" eintrage, erhält der Setter den Wert "10045", etc.

Wenn ich dann ein "a" eingeben, zeigt plötzlich die TextBox den richtigen Wert, d. H. "100". Das Gleiche passiert, wenn ich weiterhin Zahlen eintippe, bis der Int überläuft.

Wie kann ich das beheben?

Antwort

3

Versuchen in XAML Explicit statt Property mit:

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

und in Code hinter Update statt Update

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

es getestet und es funktioniert. Btw wird dieses Problem wahrscheinlich in einer späteren Version von .NET gelöst werden.

0

Sie können PropertyChanged verwenden. Versuchen Sie jedoch, eine Bindung an die EditValueProperty-Abhängigkeit statt an die TextProperty-Abhängigkeit (oder -Ereignisse) herzustellen. Es wird wie gewünscht funktionieren.