2012-05-16 7 views
50

¿Cómo puedo hacer una actualización de enlace de datos tan pronto como se escribe un nuevo carácter en un TextBox?

Estoy aprendiendo sobre encuadernaciones en WPF y ahora me he quedado atascado en un (ojalá) simple asunto.Haciendo que un WPF TextBox encienda fuego en cada nuevo personaje?

Tengo una clase FileLister simple donde puede establecer una propiedad de ruta, y luego le dará una lista de archivos cuando acceda a la propiedad FileNames. aquí es que la clase:

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

estoy usando el de la FileLister como StaticResource en esta aplicación muy simple:

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

La unión está trabajando. Si cambio el valor en el cuadro de texto y luego hago clic fuera de él, el contenido del cuadro de lista se actualizará (siempre que exista la ruta).

El problema es que me gustaría actualizar tan pronto como se escriba un nuevo carácter, y no esperar hasta que el cuadro de texto pierda el foco.

¿Cómo puedo hacer eso? ¿Hay alguna manera de hacerlo directamente en el xaml, o tengo que manejar eventos TextChanged o TextInput en el cuadro?

Respuesta

84

En unión de su cuadro de texto, todo lo que tiene que hacer es configurar UpdateSourceTrigger=PropertyChanged.

+1

Gracias! Exactamente la solución más simple que esperaba :) – luddet

+0

Para mí no funcionó ... Quiero que el texto vuelva a su valor anterior, en caso de que no sea un número. Solo cuando se agregó IsAsync = True, funcionó. – ilans

20

usted tiene que establecer la propiedad 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

De repente, el enlace de datos entre el control deslizante y el TextBox asociado generó problemas. Por fin encontré el motivo y pude arreglarlo. El convertidor utilizo:

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

En XAML

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

aún más el cuadro de texto definido

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