2012-05-16 8 views
50

Come posso aggiornare un binding di dati non appena un nuovo carattere viene digitato in un TextBox?

Sto imparando a conoscere i binding in WPF e ora mi sono bloccato su una (si spera) semplice questione.Creazione di un WPF TextBox che attiva il fuoco su ogni nuovo carattere?

Ho una semplice classe FileLister in cui è possibile impostare una proprietà Path e quindi verrà fornito un elenco di file quando si accede alla proprietà FileNames. Ecco quella classe:

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)); 
     } 
    } 
} 

Sto utilizzando il la FileLister come StaticResource in questa semplice applicazione:

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

Il legame sta lavorando. Se cambio il valore nella casella di testo e poi clic al di fuori di esso, il contenuto della casella di riepilogo si aggiornerà (finché il percorso esiste).

Il problema è che vorrei aggiornare non appena un nuovo carattere è stato digitato, e non aspettare fino a quando la casella di testo non ha perso lo stato attivo.

Come posso farlo? C'è un modo per farlo direttamente in xaml, o devo gestire eventi TextChanged o TextInput sulla scatola?

risposta

84

In vincolante vostra casella di testo, tutto quello che dovete fare è impostare UpdateSourceTrigger=PropertyChanged.

+1

Grazie! Esattamente come una soluzione semplice come speravo :) – luddet

+0

Per me non ha funzionato ... Voglio riportare il testo al suo valore precedente, nel caso non fosse un numero. Solo quando aggiunto IsAsync = True ha funzionato. – ilans

20

è necessario impostare la proprietà UpdateSourceTrigger a PropertyChanged

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

All'improvviso l'associazione dei dati tra il dispositivo di scorrimento e TextBox associato ha creato problemi. Finalmente ho trovato il motivo e ho potuto risolverlo. Il convertitore che uso:

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; 
     } 
    } 
} 

in XAML

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

ulteriormente il TextBox definito

<TextBox x:Name="TextSlidVolume" 
    Text="{Binding ElementName=SlidVolume, Path=Value, 
     Converter={StaticResource ToOneDecimalConverter},Mode=TwoWay}" 
/>