2010-07-08 2 views
2

내 응용 프로그램에 내 클래스의 소수 필드에 바인딩 된 데이터 인 텍스트 상자가 있고 바인딩 모드가 두 가지입니다. 통화 서식 지정에 StringFormat = {0 : c}을 사용하고 있습니다.WPF에서 UpdateSourceTrigger = PropertyChanged 및 StringFormat의 문제점

'UpdateSourceTrigger'를 터치하지 않는 한 정상적으로 작동합니다. UpdateSourceTrigger = PropertyChanged를 설정하면 입력중인 텍스트의 서식이 중지됩니다.

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 여기

내 코드 예제

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입니다 = PropertyCha nge '위의 코드에서 잘 작동합니다.

또한 StringFormat 대신 Converter를 사용해 보았지만 여전히 문제는 해결되지 않았습니다.

+0

모든 바인딩 오류가 발생하고 있습니까? –

+0

아니요, 표시되는 텍스트의 형식을 지정하지 않습니다. 그렇지 않으면 잘 작동합니다. 전혀 오류가 없습니다. – Elangovan

답변

5

문제는 변환기를 사용하고 속성이 변경된 경우 WPF는 원본 속성을 업데이트하는 과정에서 속성 변경 내용을 무시한다는 것입니다. PropertyChanged 이벤트는 setter에서 발생하므로 WPF는이를 무시합니다.

텍스트 상자에 "1"을 입력하면 10 진수 값 1.0으로 변환 된 다음 다시 "$ 1.00"문자열로 변환됩니다. 이렇게하면 텍스트 상자의 텍스트가 변경되고 커서가 다시 설정되므로 "12"를 입력하면 "2 $ 1.00"이됩니다.

Employee 개체가 업데이트되고 있으며 TextBox가 새로 서식이 지정된 값을 가져 오지 않는다는 점에 유의하십시오.

실제로이 동작을 원할 경우 IsAsync=True을 바인딩에 설정하면 WPF에서 더 이상 재진입 성의 변경 사항으로 표시되지 않으며 허용 할 수 있습니다. 이것은 .NET 4.0에서도 변경되었으므로 최신 버전의 프레임 워크로 업그레이드하면 예상 한 동작을보아야합니다.

+0

실버 라이트에서 동일한 문제가 발생했으며 불행히도 실버 라이트에서 바인딩에 IsAsync 속성이 없습니다. 어떻게 우리가 실버 라이트에서 이것을 얻을 수 있습니까 ?? –

+0

Async = True로 설정하면 각 수정시 줄 시작 부분으로 캐럿을 되돌릴 수 있습니다. – Slugart

관련 문제