2011-01-28 9 views
34

C'è un modo per ottenere un TextBox in Windows Phone 7 per aggiornare il Binding in quanto l'utente digita ciascuna lettera piuttosto che dopo aver perso l'attenzione?"UpdateSourceTrigger = PropertyChanged" equivalente per un TextBox Windows Phone 7

come la seguente WPF TextBox farebbe:

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

+1 per chiedere uno o f i problemi di WP più comuni –

+0

E ancora mancante nel WP8 :( – Jedidja

risposta

51

Silverlight per WP7 non supporta la sintassi che hai elencato. Eseguire il seguente comando:

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

UpdateSourceTrigger = Explicit è un bonus intelligente qui. Che cos'è?Explicit: aggiorna la sorgente di associazione solo quando si chiama il metodo UpdateSource. Ti salva un set di rilegature aggiuntivo quando l'utente lascia lo TextBox.

In 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

Risolto il problema "Uno specifico" relativo al binding utilizzando il codice "BindingExpression" sopra. Un sacco di ringraziamenti per aver reso felice il mio codice. – Jsinh

5

Non attraverso il legame della sintassi, no, ma è abbastanza facile senza. È necessario gestire l'evento TextChanged e chiamare UpdateSource sull'associazione.

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

Questo può essere convertito in un attached behavior pure abbastanza facilmente.

1

Nella chiamata di evento TextChanged UpdateSource().

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

Mi piace usare una proprietà associata. Nel caso fossi in quei piccoli bastardi.

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

E quindi il codice di protezione.

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

Fare attenzione a utilizzare questa tecnica, può introdurre perdite di memoria quando il gestore eventi non viene mai annullato. http://sharpfellows.com/post/Memory-Leaks-and-Dependency-Properties.aspx –

+0

@FlatlinerDOA: in questo caso non vi è alcun rischio di perdita di memoria perché il riferimento proviene dall'oggetto non statico (TextBox) al gestore di eventi statici (BindingUtility.OnTextChanged). Il problema sarebbe stato se il riferimento fosse il contrario. –

+0

@Parrhesia Joe, ho allegato il comportamento nella maggior parte del mio toolkit casella di testo, in una casella di testo ho usato ' 'questo ha alcuni problemi, sembra che il cursore vada al primo elemento quando premo 0 – Eldho

0

UpdateSourceTrigger = non funziona esplicita per me, quindi Im usando classe personalizzata derivated da TextBox

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

} 
0

E 'solo una riga di codice!

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

È possibile creare un generico evento TextChanged (ad esempio "ImmediateTextBox_TextChanged") nel codice dietro della vostra pagina, e poi collegarlo a qualsiasi TextBox nella pagina.

1

si può scrivere il proprio comportamento TextBox per gestire Aggiornamento su TextChanged:

Questo è il mio campione PasswordBox ma è possibile semplice modifica a gestire qualsiasi proprietà del qualsiasi oggetto.

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

ho preso Praetorian's answer e ho fatto una classe di estensione che eredita TextBox in modo che non c'è bisogno di confondere Codice del vostro vista dietro a questo comportamento.

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 

Poi chiama simili in XAML:

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