如何延迟 WPF 中绑定的更新

9
有没有一种简单的方法告诉双向WPF数据绑定在最后一次更改后等待几毫秒再使用新属性值更新源?我正在为ListBox实现一个过滤器功能,其中有一个文本框,我想根据我的输入来过滤ListBox的内容。我使用数据绑定将这些部分连接在一起。过滤列表可能需要很长时间,因此我不想在输入每个字符后都进行过滤:这就是我的请求。我一直在使用Paul Stovell的DelayBinding扩展(他的网站暂时无法访问,因此我无法链接到它)。但是,我怀疑它是我的应用程序中内存泄漏的原因(由于它未删除事件处理程序引起)。还有其他任何想法吗?

只是确认一下,我遇到了与DelayBinding类似的问题。我有一个MVVM外壳应用程序,其中包含一个StackPanel,里面装满了菜单按钮和一个主ContentControl。ContentControl.Content由Shell ViewModel上的属性设置,但是如果我加载了一个包含DelayBinding的UserControl,然后切换Content,内存使用量就会飙升。内存分析器证实,旧的Content UserControls被GC阻止回收。 - LiamV
3个回答

18

我晚了几年,但如果您正在使用WPF 4.5+,现在有一个专门用于此目的的属性,它被称为Delay

说明

在更新绑定源之前等待的时间(以毫秒为单位)。

示例用法

<TextBlock Text="{Binding Name, Delay=500}"/>

5
我有点晚回答这个问题(几年了 :)),但对于任何有兴趣的人,我在一个项目中有类似的要求,所以我创建了两个标记扩展,称为DelayBindingExtensionDelayMultiBindingExtension
它们像普通的Bindings一样工作,并额外添加了可以指定UpdateSourceDelay和/或UpdateTargetDelay的功能,两者都是TimeSpan属性。此外,我已经验证它没有泄漏(它利用继承上下文通过依赖属性绑定的propertychanged回调而不是DependencyPropertyDescriptorDelayBinding的示例用法:
<TextBox Text="{db:DelayBinding Path=TextProperty,
                                UpdateSourceTrigger=PropertyChanged,
                                UpdateSourceDelay='00:00:01'}"/>

对于一个DelayMultiBinding

<cs:ColorSelector.SelectedColor>
    <db:DelayMultiBinding Mode="TwoWay"
                          Converter="{StaticResource ColorConverter}"
                          UpdateSourceDelay="00:00:02"
                          UpdateTargetDelay="00:00:01">
        <Binding Path="Red" />
        <Binding Path="Green" />
        <Binding Path="Blue" />
    </db:DelayMultiBinding>
</cs:ColorSelector.SelectedColor>

您可以在此处下载 DelayBindingDelayMultiBinding 的源代码和示例用法:链接
如果您对其实现细节感兴趣,可以查看我在这篇博客文章中的介绍:DelayBinding 和 DelayMultiBinding 的源和目标延迟

1
我知道这是一个旧的答案,但如果你正在使用 .Net Framework 4.5,那么有一个延迟属性。详情请见:http://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.delay.aspx - Daniel Castro
看起来大家都迟到了,但还是谢谢你提供这个,它的使用非常完美。我的问题是:它看起来相当沉重,会不会对性能产生太大影响? - Kilazur
1
@Kilazur:我已经有一段时间没有看过这个实现了,但它不应该对性能产生明显影响。我在几乎每个项目中都在使用它,但我从来没有注意到任何性能下降的情况 :-) - Fredrik Hedblad
这种解决方案的一个限制是属性无法快速连续地更改。在这种情况下,绑定将不起作用,因为在新值设置到目标之前,内部计时器将停止。 - YantingChen

2
首先,为了回答你的问题,我建议添加UpdateSourceTrigger绑定扩展来控制绑定更新的时间。首选尝试LostFocus,但听起来你可能想选择Explicit。
其次,如果你的过滤需要很长时间,我建议在ListBox上使用CollectionViewSource。Bea Stollnitz对此有很好的介绍,你可以在这里找到。我使用这篇博客文章来学习如何进行过滤。当我切换到CollectionViewSource后,即使它们使用相同的过滤函数,我还是注意到了巨大的速度差异。此外,如果你绑定到ObservableCollection,CollectionViewSource会自动处理更新被过滤的项,甚至可以处理单个项的更新(这是我切换到CollectionViewSource的原因)。
希望我的回答能对你有所帮助。

谢谢Bryan。我知道UpdateSourceTrigger=Explicit,但我希望有人能提供一个现成的解决方案(类似于DelayBinding),可以在延迟后触发更新。 - Samuel Jack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接