Existe-t-il un moyen d’obtenir une zone de texte dans Windows Phone 7 pour mettre à jour la liaison lorsque l’utilisateur tape chaque lettre plutôt qu’après avoir perdu le focus?
Comme le fait le WPF TextBox suivant:
<TextBox Text="{Binding Path=TextProperty, UpdateSourceTrigger=PropertyChanged}"/>
Silverlight pour WP7 ne prend pas en charge la syntaxe que vous avez indiquée. Procédez plutôt comme suit:
<TextBox TextChanged="OnTextBoxTextChanged"
Text="{Binding MyText, Mode=TwoWay,
UpdateSourceTrigger=Explicit}" />
UpdateSourceTrigger = Explicit
est un bonus intelligent ici. Qu'est-ce que c'est? Explicit : Met à jour la source de liaison uniquement lorsque vous appelez la méthodeUpdateSource
. Vous enregistrez un jeu de liaison supplémentaire lorsque l'utilisateur quitte la variableTextBox
.
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();
}
J'aime utiliser une propriété attachée. Juste au cas où vous aimeriez ces petits idiots.
<toolkit:DataField Label="Name">
<TextBox Text="{Binding Product.Name, Mode=TwoWay}" c:BindingUtility.UpdateSourceOnChange="True"/>
</toolkit:DataField>
Et puis le code de support.
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();
}
}
}
Pas via la syntaxe de liaison, non, mais c'est assez facile sans. Vous devez gérer l'événement TextChanged et appeler UpdateSource sur la liaison.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
((TextBox) sender).GetBindingExpression( TextBox.TextProperty ).UpdateSource();
}
Cela peut être converti en un comportement attaché aussi bien assez facilement.
Vous pouvez écrire votre propre comportement TextBox pour gérer la mise à jour sur TextChanged:
Ceci est mon exemple pour PasswordBox mais vous pouvez le changer pour gérer n'importe quelle propriété de n'importe quel objet.
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>
Dans l'événement TextChanged, appelez UpdateSource () .
BindingExpression be = itemNameTextBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
J'ai pris la réponse de Praetorian et ai créé une classe d'extension qui hérite de TextBox
afin que vous n'ayez pas à confondre le code de votre vue avec ce comportement.
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
Puis appelez comme ceci dansXAML:
<local:TextBoxUpdate Text="{Binding PersonName, Mode=TwoWay}"/>
C'est juste une ligne de code!
(sender as TextBox).GetBindingExpression(TextBox.TextProperty).UpdateSource();
Vous pouvez créer un événement TextChanged générique (par exemple, "ImmediateTextBox_TextChanged") dans le code situé derrière votre page et le lier à n'importe quelle zone de texte de la page.
UpdateSourceTrigger = Explicit ne fonctionne pas pour moi, donc j'utilise une classe personnalisée dérivée de TextBox
public class TextBoxEx : TextBox
{
public TextBoxEx()
{
TextChanged += (sender, args) =>
{
var bindingExpression = GetBindingExpression(TextProperty);
if (bindingExpression != null)
{
bindingExpression.UpdateSource();
}
};
}
}