2012-05-16 23 views
50

Làm cách nào để cập nhật ràng buộc dữ liệu ngay khi ký tự mới được nhập vào một Hộp văn bản?

Tôi đang tìm hiểu về các ràng buộc trong WPF và bây giờ tôi đã trở thành khó khăn trên một (hy vọng) vấn đề đơn giản.Làm cho một hộp văn bản WPF bắt buộc lửa trên mỗi nhân vật mới?

Tôi có một lớp FileLister đơn giản, nơi bạn có thể đặt thuộc tính Đường dẫn và sau đó nó sẽ cung cấp cho bạn danh sách tệp khi bạn truy cập thuộc tính FileNames. Đây là lớp rằng:

class FileLister:INotifyPropertyChanged { 
    private string _path = ""; 

    public string Path { 
     get { 
      return _path; 
     } 
     set { 
      if (_path.Equals(value)) return; 
      _path = value; 
      OnPropertyChanged("Path"); 
      OnPropertyChanged("FileNames"); 
     } 
    } 

    public List<String> FileNames { 
     get { 
      return getListing(Path); 
     } 
    } 

    private List<string> getListing(string path) { 
     DirectoryInfo dir = new DirectoryInfo(path); 
     List<string> result = new List<string>(); 
     if (!dir.Exists) return result; 
     foreach (FileInfo fi in dir.GetFiles()) { 
      result.Add(fi.Name); 
     } 
     return result; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string property) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs(property)); 
     } 
    } 
} 

Tôi đang sử dụng các FileLister như một StaticResource trong ứng dụng rất đơn giản này:

<Window x:Class="WpfTest4.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfTest4" 
    Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <local:FileLister x:Key="fileLister" Path="d:\temp" /> 
    </Window.Resources> 
    <Grid> 
     <TextBox Text="{Binding Source={StaticResource fileLister}, Path=Path, Mode=TwoWay}" 
     Height="25" Margin="12,12,12,0" VerticalAlignment="Top" /> 
     <ListBox Margin="12,43,12,12" Name="listBox1" ItemsSource="{Binding Source={StaticResource ResourceKey=fileLister}, Path=FileNames}"/> 
    </Grid> 
</Window> 

Các ràng buộc đang làm việc. Nếu tôi thay đổi giá trị trong hộp văn bản và sau đó nhấp vào bên ngoài của nó, nội dung hộp danh sách sẽ cập nhật (miễn là đường dẫn tồn tại).

Vấn đề là tôi muốn cập nhật ngay khi ký tự mới được nhập và không đợi đến khi hộp văn bản mất tiêu điểm.

Tôi có thể làm như thế nào? Có cách nào để thực hiện điều này trực tiếp trong xaml hay tôi phải xử lý các sự kiện TextChanged hoặc TextInput trên hộp?

Trả lời

84

Trong textbox của bạn ràng buộc, tất cả các bạn phải làm là thiết lập UpdateSourceTrigger=PropertyChanged.

+1

Cảm ơn! Chính xác như giải pháp đơn giản như tôi đã hy vọng cho :) – luddet

+0

Đối với tôi nó đã không làm việc ... Tôi muốn có được văn bản trở lại giá trị trước đó của nó, trong trường hợp nó không phải là một số. Chỉ khi được thêm IsAsync = True nó đã làm việc. – ilans

20

Bạn cần phải thiết lập các UpdateSourceTrigger tài sản để PropertyChanged

<TextBox Text="{Binding Source={StaticResource fileLister}, Path=Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
    Height="25" Margin="12,12,12,0" VerticalAlignment="Top" /> 
0

Đột nhiên, liên kết dữ liệu giữa thanh trượt và TextBox liên quan gây ra sự cố. Cuối cùng tôi đã tìm ra lý do và có thể sửa chữa nó. Bộ chuyển đổi tôi sử dụng:

using System; 
using System.Globalization; 
using System.Windows.Data; 
using System.Threading; 

namespace SiderExampleVerticalV2 
{ 
    internal class FixCulture 
    { 
     internal static System.Globalization.NumberFormatInfo currcult 
       = Thread.CurrentThread.CurrentCulture.NumberFormat; 

     internal static NumberFormatInfo nfi = new NumberFormatInfo() 
     { 
      /*because manual edit properties are not treated right*/ 
      NumberDecimalDigits = 1, 
      NumberDecimalSeparator = currcult.NumberDecimalSeparator, 
      NumberGroupSeparator = currcult.NumberGroupSeparator 
     }; 
    } 

    public class ToOneDecimalConverter : IValueConverter 
    { 
     public object Convert(object value, 
      Type targetType, object parameter, CultureInfo culture) 
     { 
      double w = (double)value; 
      double r = Math.Round(w, 1); 
      string s = r.ToString("N", FixCulture.nfi); 
      return (s as String); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      string s = (string)value; 
      double w; 
      try 
      { 
       w = System.Convert.ToDouble(s, FixCulture.currcult); 
      } 
      catch 
      { 
       return null; 
      } 
      return w; 
     } 
    } 
} 

Trong XAML

<Window.Resources> 
    <local:ToOneDecimalConverter x:Key="ToOneDecimalConverter"/> 
</Window.Resources> 

thêm TextBox định nghĩa

<TextBox x:Name="TextSlidVolume" 
    Text="{Binding ElementName=SlidVolume, Path=Value, 
     Converter={StaticResource ToOneDecimalConverter},Mode=TwoWay}" 
/> 
Các vấn đề liên quan