2010-07-08 46 views
2

我在我的应用程序中有一个文本框,它绑定到我的类中的小数字段,绑定模式是双向的。我正在使用StringFormat = {0:c}进行货币格式化。UpdateSourceTrigger = WPF中PropertyChanged和StringFormat的问题

只要我不触摸'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

是你得到任何绑定错误? – 2010-07-08 03:49:07

+0

不,它不会合成显示的文本。否则,它工作正常。根本没有错误。 – Elangovan 2010-07-08 05:16:03

回答

5

问题是,如果您使用转换器和更新属性更改,然后WPF将忽略属性更改,而它是更新源属性的过程。由于setter引发了PropertyChanged事件,因此WPF忽略它。

它这样做的原因是,如果您在文本框中键入“1”,这将转换为十进制值1.0,然后转换回字符串“$ 1.00”。这将更改文本框中的文本并重置光标,因此如果您尝试键入“12”,则最终会出现“2 $ 1.00”。

请注意您的Employee对象正在更新,问题在于TextBox没有获取新格式的值。

如果你真的想要这种行为,你可以在绑定上设置IsAsync=True,并且WPF将不再将其视为可重入更改并允许它。这在.NET 4.0中也发生了变化,所以如果你升级到最新版本的框架,那么你应该看到你期望的行为。

+0

我在silverlight中遇到了同样的问题,但不幸的是,在silverlight中,您没有绑定中的IsAsync属性。 我们如何才能在silverlight中实现这一点? – 2013-02-27 05:24:17

+0

设置Async = True似乎将插入符号移回每次修改的行首 - 不能超级使用 – Slugart 2015-05-04 09:27:41

相关问题