WPF TextBox EventTrigger事件序列

时间:2017-05-29 08:47:25

标签: c# wpf xaml events textbox

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

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

问题是TextChanged属性似乎在设置bound属性的值之前触发。这意味着虽然命令触发并执行脚本,但当前正在编辑的字段将具有“旧”字样。其中的数据仍然是由于事件的顺序。

我正在使用的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. 绑定字段更新
  5. 但我需要它更像:

    1. 用户输入内容
    2. 文字已更改被解雇
    3. 绑定字段更新
    4. 命令被解雇
    5. 是否有更好的事件可以解雇或完成我想要做的事情?

2 个答案:

答案 0 :(得分:2)

您可以使用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数据传输回模型层后立即触发。

答案 1 :(得分:1)

  

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

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

您只需简单地为集合中的每个项目挂接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<T>,您还应该记住将事件处理程序添加到您添加到集合中的每个新项目。您可以通过处理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);
        }
    }
}