2011-01-28 15 views
34

¿Hay alguna manera de obtener un TextBox en Windows Phone 7 para actualizar la vinculación a medida que el usuario escribe cada letra en lugar de perder el foco?"UpdateSourceTrigger = PropertyChanged" equivalente para Windows Phone 7 TextBox

Al igual que el siguiente cuadro de texto WPF haría:

<TextBox Text="{Binding Path=TextProperty, UpdateSourceTrigger=PropertyChanged}"/> 
+1

+1 para pedir uno o f los problemas de WP más comunes –

+0

Y aún falta en WP8 :( – Jedidja

Respuesta

51

Silverlight para WP7 no es compatible con la sintaxis que ha enumerado. Haga lo siguiente en su lugar:

<TextBox TextChanged="OnTextBoxTextChanged" 
     Text="{Binding MyText, Mode=TwoWay, 
       UpdateSourceTrigger=Explicit}" /> 

UpdateSourceTrigger = Explicit es una ventaja inteligente aquí. ¿Qué es?Explicit: Actualiza la fuente de enlace solo cuando llama al método UpdateSource. Le ahorra un conjunto de enlaces extra cuando el usuario abandona el TextBox.

En C#:

private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e) 
{ 
    TextBox textBox = sender as TextBox; 
    // Update the binding source 
    BindingExpression bindingExpr = textBox.GetBindingExpression(TextBox.TextProperty); 
    bindingExpr.UpdateSource(); 
} 
+0

Se resolvió el problema "específico específico" relacionado con el enlace utilizando el código "BindingExpression" anterior. Muchísimas gracias por hacer feliz mi código. – Jsinh

5

No a través de la unión de sintaxis, no, pero es bastante fácil y sin. Debe manejar el evento TextChanged y llamar al UpdateSource en el enlace.

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
{ 
    ((TextBox) sender).GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
} 

Este se puede convertir en un attached behavior así bastante fácilmente.

1

En la llamada al evento TextChanged UpdateSource().

BindingExpression be = itemNameTextBox.GetBindingExpression(TextBox.TextProperty); 
be.UpdateSource(); 
23

me gusta usar una propiedad adjunta. Por si acaso te interesan esos pequeños cabrones.

<toolkit:DataField Label="Name"> 
    <TextBox Text="{Binding Product.Name, Mode=TwoWay}" c:BindingUtility.UpdateSourceOnChange="True"/> 
</toolkit:DataField> 

Y luego el código de respaldo.

public class BindingUtility 
{ 
public static bool GetUpdateSourceOnChange(DependencyObject d) 
{ 
    return (bool)d.GetValue(UpdateSourceOnChangeProperty); 
} 

public static void SetUpdateSourceOnChange(DependencyObject d, bool value) 
{ 
    d.SetValue(UpdateSourceOnChangeProperty, value); 
} 

// Using a DependencyProperty as the backing store for … 
public static readonly DependencyProperty 
    UpdateSourceOnChangeProperty = 
    DependencyProperty.RegisterAttached(
    "UpdateSourceOnChange", 
    typeof(bool), 
       typeof(BindingUtility), 
    new PropertyMetadata(false, OnPropertyChanged)); 

private static void OnPropertyChanged (DependencyObject d, 
    DependencyPropertyChangedEventArgs e) 
{ 
    var textBox = d as TextBox; 
    if (textBox == null) 
    return; 
    if ((bool)e.NewValue) 
    { 
    textBox.TextChanged += OnTextChanged; 
    } 
    else 
    { 
    textBox.TextChanged -= OnTextChanged; 
    } 
} 
static void OnTextChanged(object s, TextChangedEventArgs e) 
{ 
    var textBox = s as TextBox; 
    if (textBox == null) 
    return; 

    var bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty); 
    if (bindingExpression != null) 
    { 
    bindingExpression.UpdateSource(); 
    } 
} 
} 
+1

Tenga cuidado al usar esta técnica, puede presentar pérdidas de memoria ya que el controlador de eventos nunca se cancela. http://sharpfellows.com/post/Memory-Leaks-and-Dependency-Properties.aspx –

+0

@FlatlinerDOA: En este caso, no hay riesgo de pérdida de memoria porque la referencia es desde el objeto no estático (TextBox) al controlador de eventos estáticos (BindingUtility.OnTextChanged). El problema habría sido si la referencia fuera al revés. –

+0

@Parrhesia Joe, me he fijado en el comportamiento de la mayor parte de mi kit de herramientas de texto, en un cuadro de texto que he utilizado ' 'esto tiene algunos problemas, parece que el cursor va al primer elemento cuando presiono 0 – Eldho

0

UpdateSourceTrigger = no funciona explícita para mí, por lo tanto, Im usando clase personalizada que se derive del cuadro de texto

public class TextBoxEx : TextBox 
{ 
    public TextBoxEx() 
    { 
     TextChanged += (sender, args) => 
          { 
           var bindingExpression = GetBindingExpression(TextProperty); 
           if (bindingExpression != null) 
           { 
            bindingExpression.UpdateSource(); 
           } 
          }; 
    } 

} 
0

Es sólo una línea de código!

(sender as TextBox).GetBindingExpression(TextBox.TextProperty).UpdateSource(); 

Puede crear un evento genérico TextChanged (por ejemplo, "ImmediateTextBox_TextChanged") en el código detrás de la página, y que vincularlo a cualquier cuadro de texto en la página.

1

Usted puede escribir su propio comportamiento cuadro de texto para manejar Actualización sobre TextChanged:

Ésta es mi muestra a PasswordBox pero se puede cambiar fácil que para manejar cualquier propiedad del cualquier objeto.

public class UpdateSourceOnPasswordChangedBehavior 
    : Behavior<PasswordBox> 
{ 
    protected override void OnAttached() 
    { 
     base.OnAttached(); 
     AssociatedObject.PasswordChanged += OnPasswordChanged; 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 
     AssociatedObject.PasswordChanged -= OnPasswordChanged; 
    } 

    private void OnPasswordChanged(object sender, RoutedEventArgs e) 
    { 
     AssociatedObject.GetBindingExpression(PasswordBox.PasswordProperty).UpdateSource(); 
    } 
} 

ussage:

<PasswordBox x:Name="Password" Password="{Binding Password, Mode=TwoWay}" > 
    <i:Interaction.Behaviors> 
     <common:UpdateSourceOnPasswordChangedBehavior/> 
    </i:Interaction.Behaviors> 
</PasswordBox> 
0

Tomé Praetorian's answer e hice una clase de extensión que hereda TextBox por lo que no tienen que salir del paso hasta el código de la vista detrás de este comportamiento.

C-Sharp:

public class TextBoxUpdate : TextBox 
{ 
    public TextBoxUpdate() 
    { 
     TextChanged += OnTextBoxTextChanged; 
    } 
    private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e) 
    { 
     TextBox senderText = (TextBox)sender; 
     BindingExpression bindingExp = senderText.GetBindingExpression(TextBox.TextProperty); 
     bindingExp.UpdateSource(); 
    } 
} 

VisualBasic:

Public Class TextBoxUpdate : Inherits TextBox 

    Private Sub OnTextBoxTextChanged(sender As Object, e As TextChangedEventArgs) Handles Me.TextChanged 
     Dim senderText As TextBox = DirectCast(sender, TextBox) 
     Dim bindingExp As BindingExpression = senderText.GetBindingExpression(TextBox.TextProperty) 
     bindingExp.UpdateSource() 
    End Sub 

End Class 

A continuación, llame así en XAML:

<local:TextBoxUpdate Text="{Binding PersonName, Mode=TwoWay}"/>