2010-07-08 18 views
2

J'ai une zone de texte dans mon application qui est liée à un champ décimal dans ma classe et le mode de liaison est bidirectionnel. J'utilise StringFormat = {0: c} pour le formatage des devises.Problème avec UpdateSourceTrigger = PropertyChanged et StringFormat dans WPF

Cela fonctionne très bien tant que je ne touche pas 'UpdateSourceTrigger'. Si je définis UpdateSourceTrigger = PropertyChanged, il arrête de formater le texte que j'entre.

ici est mon exemple de code

Employee.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 

namespace Converter 
{ 
    public class Employee : INotifyPropertyChanged 
    { 
     int _employeeNumber; 
     string _firstName; 
     string _lastName; 
     string _department; 
     string _title; 
     decimal _salary; 

     public Employee() 
     { 
      _employeeNumber = 0; 
      _firstName = 
       _lastName = 
       _department = 
       _title = null; 
     } 
     public int EmployeeNumber 
     { 
      get { return _employeeNumber; } 
      set 
      { 
       _employeeNumber = value; 
       OnPropertyChanged("EmployeeNumber"); 
      } 
     } 
     public string FirstName 
     { 
      get { return _firstName; } 
      set 
      { 
       _firstName = value; 
       OnPropertyChanged("FirstName"); 
      } 
     } 

     public string LastName 
     { 
      get { return _lastName; } 
      set 
      { 
       _lastName = value; 
       OnPropertyChanged("LastName"); 
      } 
     } 

     public string Department 
     { 
      get { return _department; } 
      set 
      { 
       _department = value; 
       OnPropertyChanged("Department"); 
      } 
     } 

     public string Title 
     { 
      get { return _title + " salary: " + _salary.ToString(); } 
      set 
      { 
       _title = value; 
       OnPropertyChanged("Title"); 
      } 
     } 

     public decimal Salary 
     { 
      get { return _salary; } 
      set 
      { 
       _salary = value;     
       OnPropertyChanged("Salary"); 
       OnPropertyChanged("Title"); 
      } 
     } 

     public override string ToString() 
     { 
      return String.Format("{0} {1} ({2})", FirstName, LastName, EmployeeNumber); 
     } 


     protected void OnPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChangedEventArgs args = new PropertyChangedEventArgs(propertyName); 
       this.PropertyChanged(this, args); 
      } 
     } 

     #region INotifyPropertyChanged Members 

     public event PropertyChangedEventHandler PropertyChanged; 

     #endregion 
    } 
} 

EmployeeList.cs:

using System.Collections.ObjectModel; 

namespace Converter 
{ 
    public class EmployeeList : ObservableCollection<Employee> 
    { 
    } 
} 

Window1.xaml:

<Window x:Class="Converter.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:Converter" 
    Title="Window1" Height="500" Width="500"> 
    <Window.Resources> 
     <local:EmployeeList x:Key="myEmployeeList"> 
      <local:Employee EmployeeNumber="1" FirstName="John" LastName="Dow" Title="Accountant" Department="Payroll" Salary="25000.00" /> 
      <local:Employee EmployeeNumber="2" FirstName="Jane" LastName="Austin" Title="Account Executive" Department="Customer Management" Salary="25000.00" /> 
      <local:Employee EmployeeNumber="3" FirstName="Ralph" LastName="Emmerson" Title="QA Manager" Department="Product Development" Salary="25000.00" /> 
      <local:Employee EmployeeNumber="4" FirstName="Patrick" LastName="Fitzgerald" Title="QA Manager" Department="Product Development" Salary="25000.00" /> 
      <local:Employee EmployeeNumber="5" FirstName="Charles" LastName="Dickens" Title="QA Manager" Department="Product Development" Salary="25000.00" />    
     </local:EmployeeList> 
     <local:StringToDecimalCurrencyConverter x:Key="StringToDecimalCurrencyConverter"></local:StringToDecimalCurrencyConverter> 
    </Window.Resources> 
    <Grid DataContext="{StaticResource myEmployeeList}"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="240" /> 
      <RowDefinition Height="45" /> 
     </Grid.RowDefinitions> 
     <ListBox Name="employeeListBox" ItemsSource="{Binding Path=., Mode=TwoWay}" Grid.Row="0" /> 
     <Grid Grid.Row="1" DataContext="{Binding ElementName=employeeListBox, Path=SelectedItem, Mode=TwoWay}"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="40" /> 
       <RowDefinition Height="40" /> 
       <RowDefinition Height="40" /> 
       <RowDefinition Height="40" /> 
       <RowDefinition Height="40" /> 
       <RowDefinition Height="40" /> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="80" /> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 
      <Label Grid.Row="0" Grid.Column="0">First Name</Label> 
      <Label Grid.Row="1" Grid.Column="0">Last Name</Label> 
      <Label Grid.Row="2" Grid.Column="0">Title</Label> 
      <Label Grid.Row="3" Grid.Column="0">Department</Label> 
      <Label Grid.Row="4" Grid.Column="0">Salary</Label> 

      <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Mode=TwoWay, Path=FirstName}" /> 
      <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Mode=TwoWay, Path=LastName}" /> 
      <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Mode=TwoWay, Path=Title}" /> 
      <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Mode=TwoWay, Path=Department}" /> 
      <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Mode=TwoWay, StringFormat=\{0:c\}, UpdateSourceTrigger=PropertyChanged, Path=Salary}" /> 
      <TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding Mode=OneWay, Converter={StaticResource StringToDecimalCurrencyConverter}, Path=Salary}" /> 
     </Grid>   
    </Grid> 
</Window> 

Si vous supprimez « UpdateSourceTrigger = PropertyCha nged 'du code ci-dessus cela fonctionne bien.

J'ai également essayé d'utiliser Converter au lieu de StringFormat, et le problème n'est toujours pas résolu.

+0

Des erreurs de liaison se produisent-elles? –

+0

non, il ne forme pas le texte affiché. Sinon, cela fonctionne bien. pas d'erreur du tout. – Elangovan

Répondre

5

Le problème est que si vous utilisez un convertisseur et que la mise à jour sur la propriété a été modifiée, WPF ignore les changements de propriété alors que c'est le processus de mise à jour de la propriété source. Étant donné que l'événement PropertyChanged est généré à partir du setter, WPF l'ignore. La raison pour laquelle ceci est ceci est que si vous avez tapé "1" dans la zone de texte, ceci serait converti en la valeur décimale 1.0, puis serait reconverti en la chaîne "$ 1,00". Cela changerait le texte dans la zone de texte et réinitialiserait le curseur, donc si vous essayiez de taper "12" vous finiriez avec "2 $ 1.00".

Notez que votre objet Employee est mis à jour et que le problème est simplement que TextBox n'obtient pas une nouvelle valeur formatée.

Si vous voulez vraiment ce comportement, vous pouvez définir IsAsync=True sur la liaison et WPF ne le verra plus comme une modification réentrante et l'autorisera. Cela a également changé dans .NET 4.0, donc si vous mettez à niveau vers la dernière version du framework, vous devriez voir le comportement que vous attendez.

+0

J'ai le même problème dans Silverlight et malheureusement dans Silverlight vous n'avez pas l'attribut IsAsync dans la liaison. Comment pouvons-nous y parvenir en argenté? –

+0

Réglage Async = True semble déplacer le curseur au début de la ligne à chaque modification - pas super utilisable – Slugart