【问题标题】:WPF TextBox EventTrigger sequence of eventsWPF TextBox EventTrigger 事件序列
【发布时间】:2017-05-29 08:47:25
【问题描述】:

我有一个动态 WPF 输入表单,根据数据集合的内容显示输入文本框列表。每个文本框的文本都绑定到数据中的值字段,当这些字段中的任何一个发生更改时,我正在使用触发命令,然后使用输入字段的值在脚本(也动态提供)中执行计算。

我的问题是如何在字段值更改后执行命令。目前,我正在使用 TextChanged 属性基于事件触发器触发命令。

问题在于 TextChanged 属性似乎在设置绑定属性的值之前触发。这意味着尽管命令触发并执行脚本,但由于事件的顺序,当前正在编辑的字段仍将包含“旧”数据。

我正在使用的 XAML 代码的相关位是:

<Label Visibility="{Binding HasInputFieldsSection, Converter={StaticResource visibilityConverter}}">Input parameters</Label>

<ItemsControl Visibility="{Binding HasInputFieldsSection, Converter={StaticResource visibilityConverter}}"
              ItemsSource="{Binding Path=SelectedQualificationType.QualificationTypeInputFields.QualificationTypeFields}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Label Content="{Binding Label}" Visibility="{Binding Label, Converter={StaticResource stringVisibilityConverter}}"/>

                <TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, Delay=250}">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="TextChanged">
                            <cmd:EventToCommand Command="{Binding DataContext.ExecuteExpressionsCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </TextBox>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

我希望有一个不同的事件可以触发命令,但是在查看了 WPF 文本框的文档并尝试了一些替代方法之后,它们似乎都不合适。

我可以将绑定更改为基于 LostFocus 而不是 PropertyChanged,但为了更好的用户体验,我宁愿不这样做。同样,我可以消除输入 TextBox 绑定的延迟,但理想情况下,我希望保持这种延迟,再次为用户体验。

所以简而言之,当前的顺序似乎是:

  1. 用户输入内容
  2. 文本更改被触发
  3. 命令被触发
  4. 绑定字段得到更新

但我需要它更像:

  1. 用户输入内容
  2. 文本更改被触发
  3. 绑定字段得到更新
  4. 命令被触发

是否有更好的事件来触发或完成我想要做的事情?

【问题讨论】:

    标签: c# wpf xaml events textbox


    【解决方案1】:

    您可以使用Binding.SourceUpdated Attached Event 代替TextChanged 事件。

    Binding 上的Binding.NotifyOnSourceUpdated 属性设置为true 并监听附加事件:

    <TextBox Text="{Binding Value, NotifyOnSourceUpdated=True}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SourceUpdated">
                <!--...-->
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
    

    使用这种方法,您的命令将在 Binding 数据传输回模型层后立即触发。

    【讨论】:

      【解决方案2】:

      我的问题是如何在字段值更改后执行命令。目前,我正在使用 TextChanged 属性基于事件触发器触发命令。

      当设置QualificationTypeFields 集合中任何项目的Value 属性时,在视图模型中触发该命令。

      您可以简单地为集合中的每个项目的PropertyChanged 事件连接一个事件处理程序,如下所示:

      foreach(var item in SelectedQualificationType.QualificationTypeInputFields.QualificationTypeFields)
      {
          item.PropertyChanged += item_PropertyChanged;   
      }
      
      ...
      
      private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
          if (e.PropertyName == "Value")
          {
              ExecuteExpressionsCommand.Execute(null);
          }
      }
      

      如果QualificationTypeFieldsObservableCollection&lt;T&gt;,您还应该记住将事件处理程序添加到您添加到集合中的每个新项目。您可以通过处理CollectionChanged 事件轻松做到这一点:

      private void QualificationTypeFields_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
      {
          if (e.NewItems != null)
          {
              foreach (object item in e.NewItems)
              {
                  (item as INotifyPropertyChanged).PropertyChanged
                      += new PropertyChangedEventHandler(item_PropertyChanged);
              }
          }
      
          if (e.OldItems != null)
          {
              foreach (object item in e.OldItems)
              {
                  (item as INotifyPropertyChanged).PropertyChanged
                      -= new PropertyChangedEventHandler(item_PropertyChanged);
              }
          }
      }
      

      【讨论】:

      • 非常感谢,我可以看到这也是如何工作的,但我最终还是接受了 dymanoid 提出的答案
      • 是的,ofc,会的
      猜你喜欢
      • 1970-01-01
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      相关资源
      最近更新 更多