【问题标题】:How to control "update trigger" in oneway databinding in wpf?如何在 wpf 的单向数据绑定中控制“更新触发器”?
【发布时间】:2015-03-12 21:26:01
【问题描述】:

在 WPF 中使用数据绑定时,如果将Mode 属性设置为TwoWay,则可以通过设置UpdateSourceTrigger 属性来控制更新源属性的时刻。对于目标 -> 源更新流,这种情况是可能的。但是如何控制源 -> 目标更新流的相同内容?我找不到等效的属性。

例如,假设我的窗口上有两个文本框,我想绑定两个文本框的 Text 属性。 XAML 可能如下所示:

        <TextBox
            Name="txt1"
            Text="{Binding ElementName=txt2, Path=Text, Mode=TwoWay,
            UpdateSourceTrigger=LostFocus}"
            />
        <TextBox
            Name="txt2"
            />

当用户在txt1 TextBox 中输入文本时,txt2 Textbox 的Text 属性将随着Text 属性的变化而更新,就像我在txt1 上实现了TextChanged 事件一样。

但是,当用户在txt2 TextBox 中输入文本时,txt1 文本框的Text 属性将在txt2 TextBox 失去焦点后更新,因为UpdateSourceTrigger 属性设置为LostFocus,就像我有实现了 LostFocus 事件。

在源属性控制失去焦点后,WPF 数据绑定是否有可能更新目标属性?在我们的示例中:应该对上面的 XAML 代码做什么,所以 txt2 TextBox 的 Text 属性只会在 txt1 TextBox 失去焦点后更新,而不是在其 Text 属性更改后更新?

谢谢!

【问题讨论】:

    标签: wpf xaml 2-way-object-databinding data-binding


    【解决方案1】:

    为什么不定义两个绑定?这对我有用:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <TextBox Name="txt1" Margin="4" 
                     Text="{Binding ElementName=txt2, Path=Text, Mode=OneWay}" />
            <TextBox Name="txt2" Margin="4" 
                     Text="{Binding ElementName=txt1, Path=Text, Mode=OneWay}" />
        </StackPanel>
    </Window>
    

    【讨论】:

      【解决方案2】:

      UpdateSourceTrigger 机制与 WPF 控件的隐式性质相关联。通过这种方式,您可以决定何时更新源。 另一方面,源可以是UIElement,但也可以是另一个对象。实际上,作为绑定源的对象可以通过实现INotifyPropertyChanged 来通知其对绑定的更改。 通过这个接口,对象每次通知它的变化,一个属性发生变化。

      因此,如果您想要一种“UpdateTargetTrigger”,您应该在控件中实现它。 例如,您可以通过这种方式扩展 TextBox 控件:

      public class ExtTextBox : TextBox, INotifyPropertyChanged
      {
          private event PropertyChangedEventHandler propertyChanged;
          private string textOnLostFocus;
      
          public event PropertyChangedEventHandler PropertyChanged
          {
              add
              {
                  propertyChanged += value;
              }
              remove
              {
                  propertyChanged -= value;
              }
          }
      
          private void OnPropertyChanged(string propertyName)
          {
              if (propertyChanged != null)
              {
                  propertyChanged(this, new PropertyChangedEventArgs(propertyName));
              }
          }
      
          protected override void OnLostFocus(RoutedEventArgs e)
          {
              base.OnLostFocus(e);
              SetTextOnLostFocus(Text, false);
          }
      
          private void SetTextOnLostFocus(string text, bool updateText)
          {
              if (StringComparer.Ordinal.Compare(textOnLostFocus, text) != 0)
              {
                  textOnLostFocus = text;
                  if (updateText)
                  {
                      Text = text;
                  }
      
                  OnPropertyChanged("TextOnLostFocus");
              }
          }
      
          public string TextOnLostFocus
          {
              get
              {
                  return textOnLostFocus;
              }
              set
              {
                  SetTextOnLostFocus(Text, true);
              }
          }
      }
      

      我使用 TextOnLostFocus 作为支持,仅在 LostFocus 事件上通知其更改。 因此,您的 XAML 将是:

      <TextBox Name="txt1" Text="{Binding ElementName=txt2, Path=TextOnLostFocus, Mode=TwoWay,
                                          UpdateSourceTrigger=LostFocus}" Margin="3" />
      <local:ExtTextBox x:Name="txt2" Margin="3" />
      

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 2018-02-02
        • 1970-01-01
        • 1970-01-01
        • 2015-05-22
        • 1970-01-01
        • 2017-02-19
        • 2011-02-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多