2010-07-08 2 views
2

У меня есть текстовое поле в моем приложении, которое привязано к десятичному полю в моем классе, а режим привязки - в два пути. Я использую StringFormat = {0: c} для форматирования валюты.Проблема с UpdateSourceTrigger = PropertyChanged и StringFormat в WPF

Это прекрасно работает, если я не касаюсь «UpdateSourceTrigger». Если я установил UpdateSourceTrigger = PropertyChanged, он прекратит форматирование текста, который я вводил.

вот мой пример кода

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> 

Если удалить «UpdateSourceTrigger = PropertyCha nged 'из вышеприведенного кода работает нормально.

Я также пытался использовать Конвертер вместо StringFormat, и проблема все еще не решена.

+0

У вас есть какие-либо ошибки привязки? –

+0

нет, он не формирует отображаемый текст. В противном случае он отлично работает. никакой ошибки вообще. – Elangovan

ответ

5

Проблема заключается в том, что если вы измените конфигурацию конвертера и обновления, WPF проигнорирует изменения свойств, пока это процесс обновления исходного свойства. Поскольку событие PropertyChanged возникает из сеттера, WPF игнорирует его.

Причина в том, что если вы набрали «1» в текстовом поле, это преобразуется в десятичное значение 1.0, а затем преобразуется обратно в строку «1,00». Это изменит текст в текстовом поле и сбросит курсор, поэтому, если вы попытаетесь ввести «12», вы получите «2 $ 1,00».

Обратите внимание, что объект Employee обновляется, и проблема в том, что TextBox не получает вновь отформатированное значение.

Если вы действительно хотите этого поведения, вы можете установить IsAsync=True на привязку, и WPF больше не будет рассматривать его как повторное изменение и позволит это. Это также изменилось в .NET 4.0, поэтому, если вы обновляетесь до последней версии фреймворка, вы должны увидеть поведение, которое вы ожидаете.

+0

У меня такая же проблема в silverlight, и, к сожалению, в silverlight у вас нет атрибута IsAsync при привязке. Как мы можем достичь этого в silverlight ?? –

+0

Настройка Async = True, похоже, переводит каретку назад в начало строки для каждой модификации - не суперпользователь – Slugart

Смежные вопросы