【问题标题】:"UpdateSourceTrigger=PropertyChanged" equivalent for a Windows Phone 7 TextBoxWindows Phone 7 文本框的“UpdateSourceTrigger=PropertyChanged”等效项
【发布时间】:2011-01-28 21:11:57
【问题描述】:

有没有办法让 Windows Phone 7 中的 TextBox 在用户键入每个字母时而不是在失去焦点后更新绑定?

就像下面的 WPF TextBox 会做的那样:

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

【问题讨论】:

  • +1 用于询问最常见的 WP 问题之一
  • 在 WP8 中仍然缺失 :(

标签: c# silverlight windows-phone-7


【解决方案1】:

Silverlight for WP7 不支持您列出的语法。请改为执行以下操作:

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

UpdateSourceTrigger = Explicit 在这里是一个聪明的奖励。 这是什么? Explicit:仅在调用UpdateSource 方法时更新绑定源。当用户离开TextBox时,它会为您节省一个额外的绑定集。

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

【讨论】:

  • 使用上述“BindingExpression”代码解决了与绑定相关的“一个特定”问题。非常感谢让我的代码快乐。
【解决方案2】:

我喜欢使用附加属性。以防万一你喜欢那些小虫子。

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

然后是支持代码。

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

【讨论】:

  • 小心使用这种技术,它可能会引入内存泄漏,因为永远不会取消注册事件处理程序。 sharpfellows.com/post/…
  • @FlatlinerDOA :在这种情况下,没有内存泄漏的风险,因为引用是从非静态对象 (TextBox) 到静态事件处理程序 (BindingUtility.OnTextChanged)。如果引用是相反的,问题就会出现。
  • @Parrhesia Joe,我在我的大多数工具包文本框中都附加了行为,在我使用过的文本框中 &lt;toolkit:PhoneTextBox Hint="Last 10 Digit Card Number" Grid.Row="0" InputScope="Number" MaxLength="10" DisplayedMaxLength="10" Text="{Binding CardNumber,Mode=TwoWay}" ActionIcon="/Assets/Help.png" helpers:BindingUtility.UpdateSourceOnChange="True" KeyDown="PhoneTextBox_KeyDown"/&gt; 这有一些问题,当我按 0 时光标似乎转到第一项
【解决方案3】:

不是通过绑定语法,不,但没有它很容易。您必须处理 TextChanged 事件并在绑定上调用 UpdateSource

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

这也可以很容易地转换为attached behavior

【讨论】:

    【解决方案4】:

    在 TextChanged 事件中调用UpdateSource()

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

    【讨论】:

      【解决方案5】:

      您可以编写自己的 TextBox 行为来处理 TextChanged 上的更新:

      这是我的 PasswordBox 示例,但您可以简单地更改它以处理任何对象的任何属性。

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

      用法:

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

      【讨论】:

        【解决方案6】:

        UpdateSourceTrigger=Explicit 对我不起作用,因此我使用派生自 TextBox 的自定义类

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

        【讨论】:

          【解决方案7】:

          只有一行代码!

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

          您可以在页面后面的代码中创建一个通用的 TextChanged 事件(例如“ImmediateTextBox_TextChanged”),然后将其链接到页面中的任何 TextBox。

          【讨论】:

            【解决方案8】:

            我采用Praetorian's answer 并创建了一个继承TextBox 的扩展类,因此您不必将视图代码与此行为混淆。

            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
            

            然后在 XAML 中像这样调用:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-02-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多