2010-07-08 69 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

相關問題