WPF - 延迟多重绑定

2024-01-09

我有一个多重绑定,看起来像这样:

<UserControl.Visibility>
    <MultiBinding Converter="{StaticResource isMouseOverToVisibiltyConverter}">
        <Binding ElementName="otherElement" Path="IsMouseOver" />
        <Binding RelativeSource="{RelativeSource Self}" Path="IsMouseOver" />
    </MultiBinding>
</UserControl.Visibility>

而且,我希望能够在两个绑定的 IsMouseOver 变为 false 和 Visibility 设置为 Collapsed 之间添加延迟。

我找到了这个 DelayBinding 实现:http://www.paulstovell.com/wpf-delaybinding http://www.paulstovell.com/wpf-delaybinding

但是,这不适用于 MultiBinding,而且我一直无法弄清楚如何制作一个适用于 MultiBinding 的产品。

我确实可以选择对代码隐藏中的事件中的可见性进行更改,这会起作用,但如果有某种方法可以通过绑定系统来执行此操作,那就太好了。

有什么方法可以为多重绑定添加延迟吗?

编辑:雷,为了让你的类编译和运行,我必须进行一些修复。然而,问题仍然存在,因为更新没有被传播。它似乎只更新一次目标属性。

[ContentProperty("Bindings")]
public class DelayedMultiBindingExtension : MarkupExtension, IMultiValueConverter, INotifyPropertyChanged
{
    public Collection<BindingBase> Bindings { get; private set; }
    public IMultiValueConverter Converter { get; set; }
    public object ConverterParameter { get; set; }
    public CultureInfo ConverterCulture { get; set; }
    public BindingMode Mode { get; set; }
    public UpdateSourceTrigger UpdateSourceTrigger { get; set; }

    public object CurrentValue { get { return _delayedValue; } set { _delayedValue = _undelayedValue = value; _timer.Stop(); } }

    private object _undelayedValue;
    private object _delayedValue;

    private DispatcherTimer _timer;
    public int ChangeCount { get; private set; }  // Public so Binding can bind to it

    public DelayedMultiBindingExtension()
    {
        this.Bindings = new Collection<BindingBase>();
        _timer = new DispatcherTimer();
        _timer.Tick += _timer_Tick;
        _timer.Interval = TimeSpan.FromMilliseconds(500);
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        if (valueProvider != null)
        {
            var bindingTarget = valueProvider.TargetObject as DependencyObject;
            var bindingProperty = valueProvider.TargetProperty as DependencyProperty;

            var multi = new MultiBinding { Converter = this, Mode = Mode, UpdateSourceTrigger = UpdateSourceTrigger };
            foreach (var binding in Bindings)
                multi.Bindings.Add(binding);
            multi.Bindings.Add(new Binding("ChangeCount") { Source = this, Mode = BindingMode.OneWay });

            var bindingExpression = BindingOperations.SetBinding(bindingTarget, bindingProperty, multi);

            return bindingTarget.GetValue(bindingProperty);
        }

        return null;
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        object newValue =
          Converter.Convert(
            values.Take(values.Length - 1).ToArray(),
            targetType,
            ConverterParameter,
            ConverterCulture ?? culture);

        if (!object.Equals(newValue, _undelayedValue))
        {
            _undelayedValue = newValue;
            _timer.Stop();
            _timer.Start();
        }
        return _delayedValue;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return
          Converter.ConvertBack(value, targetTypes, ConverterParameter, ConverterCulture ?? culture)
          .Concat(new object[] { ChangeCount }).ToArray();
    }

    private void _timer_Tick(object sender, EventArgs e)
    {
        _timer.Stop();
        _delayedValue = _undelayedValue;
        ChangeCount++;
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("ChangeCount"));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

EDIT2:尽管我无法让 Ray 的代码工作,但我已将其标记为答案,因为它给我带来了一些可以工作的代码。有关我使用的代码,请参阅下面的答案。


您链接到的 DelayBinding 类仅延迟源更新,而不延迟目标更新。延迟目标更新(这正是您所要求的)要简单得多。像这样的事情应该可以解决问题:

public class DelayedMultiBindingExtension : MarkupExtension, IMultiValueConverter, INotifyPropertyChanged
{
  public Collection<Binding> Bindings { get; set; }
  public IMultiValueConverter Converter { get; set; }
  public object ConverterParameter { get; set; }
  public CultureInfo ConverterCulture { get; set; }
  public BindingMode Mode { get; set; }
  public UpdateSourceTrigger UpdateSourceTrigger { get; set; }

  public object CurrentValue { get { return _delayedValue; } set { _delayedValue = _undelayedValue = value; _timer.Stop(); } }

  object _undelayedValue;
  object _delayedValue;

  DispatcherTimer _timer;
  public int ChangeCount { get; set; }  // Public so Binding can bind to it

  public DelayedMultiBindingExtension()
  {
    _timer = new DispatcherTimer();
    _timer.Tick += _timer_Tick;
  }

  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    var multi = new MultiBinding { Converter = this, Mode = Mode, UpdateSourceTrigger = UpdateSourceTrigger };
    foreach(var binding in Bindings)
      multi.Bindings.Add(binding);
    multi.Bindings.Add(new Binding("ChangeCount") { Source = this });
    return multi;
  }

  public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  {
    object newValue =
      Converter.Convert(
        values.Take(values.Length-1).ToArray(),
        targetType,
        ConverterParameter,
        ConverterCulture ?? culture);

    if(!object.Equals(newValue, _undelayedValue))
    {
      _undelayedValue = newValue;
      _timer.Stop();
      _timer.Start();
    }
    return _delayedValue;
  }

  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
    return
      Converter.ConvertBack(value, targetTypes, ConverterParameter, ConverterCulture ?? culture)
      .Concat(new object[] { ChangeCount }).ToArray();
  }

  void _timer_Tick(object sender, EventArgs e)
  {
    _timer.Stop();
    _delayedValue = _undelayedValue;
    ChangeCount++;
    if(PropertyChanged!=null)
      PropertyChanged(this, new PropertyChangedEventArgs("ChangeCount"));
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

工作原理:构造了一个 MultiBinding,它具有一个额外的绑定,即到标记扩展本身的 ChangeCount 属性。标记扩展本身也注册为转换器。每当源值更改时,绑定就会评估并调用转换器。这又调用“实际”转换器来计算该值。它不会立即更新值,而是将其存储在 _undelayedValue 中,并返回之前的值 (_delayedValue)。此外,如果该值已更改,则会启动(或重新启动)计时器。当计时器触发时,该值将被复制到 _delayedValue 中,并且 ChangeCount 会递增,从而强制重新评估绑定。这次返回了新的 _delayedValue。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF - 延迟多重绑定 的相关文章

  • 该组件没有由 uri 标识的资源

    我想创建一个通用数据网格以在我的所有视图 用户控件上使用 这是我的结构 Class Library called Core Class called ViewBase public class ViewBase UserControl pu
  • 列表视图上的 TextBlock:如何忽略 TextBlock 中的点击并让列表视图处理它们

    我有一个显示大量信息的列表视图 但是当它为空时 我想在其上覆盖一个文本块 上面写着 没有要显示的信息 或 bla bla bla 添加信息 列表视图设置为响应鼠标单击 但现在如果我单击文本块 这些事件将路由到文本块 我怎样才能让这些事件转到
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 将 PDF 嵌入到 WPF 应用程序中

    我正在尝试在 WPF 应用程序中嵌入 显示 PDF 到目前为止 我已经尝试过这些解决方案 但没有成功 在 a 中显示 PDFWindowsFormsHost主持一个AxAcroPdf控制 类似于显示的内容here http hugeonio
  • 先学Silverlight还是先学WPF?

    看来 Silverlight WPF 是 NET 用户界面开发的长期未来 这很棒 因为我可以看到在客户端和 Web 开发端重用 XAML 技能的优势 但看看 WPF XAML Silverlight 它们似乎是非常庞大的技术 那么从哪里开始
  • WPF:Prism 对于小型应用程序来说是不是太过分了?

    如果我不将我的应用程序分成不同的模块 否则我会认为 Prism 确实是可行的方法 我应该使用 Prism 吗 我知道 Prism 提供了一个方便的实现ICommand 我可以自己在一页代码中完成 并为我们提供IEventAggregator
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • ScrollViewer 滚动条始终禁用

    我是 xaml 和 wpf 的新手 我正在尝试将一些用户控件从代码隐藏插入到容器中 我已阅读此博客文章MSDN http blogs msdn com b marcelolr archive 2009 06 09 stackpanel do
  • PreviewKeyDown 不会在 ElementHost 中针对 Tab 和箭头键触发

    我在 Winforms ElementHost 中有一个 WPF 窗口 我的窗口上的 Tab 键和箭头键不会触发 KeyDown 和 PreviewKeyDown 事件 KeyUp 和 PreviewKeyUp 似乎工作正常 Preview
  • WPF:通过拖放重新排序 WrapPanel 内容?

    我正在寻找一种通过拖放对 WPF WrapPanel 的内容 项目 重新排序的方法 我只想单击一个项目并将其拖动到新位置 据我了解 这是一项非常常见的任务 我想知道有人已经这样做了 或者知道如何实现此功能 我已经进行了谷歌搜索 但什么也没找
  • Visual Studio 扩展找不到所需的程序集

    我为 Visual Studio 2013 编写了一个扩展 因为该死的组合框错误 https stackoverflow com questions 7800032 cancel combobox selection in wpf with
  • 更改其他页面的主窗口内容

    在 WPF 应用程序的主窗口中 我有一个 Badged 元素 来自材料设计 这是我的代码
  • 如何使取消按钮像“X”按钮一样工作?

    在我的 XAML 文件中 我有一个窗口 我试图将其设置为无论用户单击 X 按钮还是单击 取消 按钮 行为都是相同的 我的缩写代码如下 public partial class Dialog Window private void Windo
  • WPFToolkit.Extended - 工具在哪里?

    我已采取的步骤 我正在使用 NET 4 0 我得codeplex http wpftoolkit codeplex com releases view 84227并下载了第一个 扩展 WPF 工具包二进制文件 2 号将此文件 Extende
  • 使用带有 prism 的 MVVM 在视图之间进行更改

    我是 WPF 新手 但根据我所读到的内容 构建应用程序的正确方法是在同一窗口上切换视图 我的意思是类似于带有菜单和显示视图的工作区的 框架 到目前为止我一直在关注这个http jesseliberty com 2011 01 06 wind
  • Azure 可以运行 WPF 吗?

    我想编写一个在 Windows Azure 上运行的 ASP Net MVC 应用程序 该应用程序将使用 WPF 创建图像 在我开始写之前 这会起作用吗 Azure 是否具有渲染 WPF 所需的 DLL 包括 DirectX 和图形功能 我
  • Xamly 将键盘焦点设置为 DataGridTemplateColumn 单元格中的元素?

    我已经在 DataGridTemplateColumn CellEditing DataTemplate 中设置了一些内容 我希望当单元格编辑加载并显示模板时 键盘焦点应该给予模板中的某个控件 考虑这个例子 当您进入编辑模式时 文本框不是以
  • 将两个垂直滚动条相互绑定

    我在控件中有两个 TextBox 并且它们都有两个 VerticalScrollBar 我想在它们之间绑定 VerticalScrollBars 如果一个向上 第二个也会向上等等 如果可以的话我该怎么做 Thanks 不是真正的绑定 但它有
  • 绑定集合的子集

    我有一个ObservableCollection

随机推荐

  • 正则表达式从 XSLT 中删除单词

    我需要帮助编写正则表达式以使用 XSLT 删除单词 我需要将 XML 文件的 详细路径 的输出更改为 活动 262 26207 简单地说 262 26207 XSL 是
  • 为什么进程终止后异步读取仍未完成?

    我编写了一个进程 它从作为参数给出的文件中读取数据 我已异步读取 StandardOutput 和同步读取 StandardError public static string ProcessScript string command st
  • 删除水晶报表中数字字段的小数

    我有一个字段年份 它是来自数据库端的字符串类型 因此我将其转换为数字 并在其中添加 1 年以显示如下 Year 2014 2015 下面是公式 Year tonumber FocusOnCustomer YEAR tonumber Focu
  • Android原生浏览器的引擎是什么?

    Android原生浏览器的引擎是什么 维基说 https en wikipedia org wiki WebKit UseAndroid 在 4 4 之前使用 WebKit 且Blink https en wikipedia org wik
  • C++中的反斜杠是什么意思?

    这段代码的作用是什么 特别是反斜杠 的作用是什么 s23 foo s8 foo s16 bar 我添加了数据类型 因为它们可能是相关的 感谢您的帮助 反斜杠在 C 中表示两种不同的事物 具体取决于上下文 作为行的延续 在引号字符串之外 见下
  • 如何在java客户端中获取HDFS服务器元数据信息?

    我需要构建一个实用程序类来测试与 HDFS 的连接 测试应显示 HDFS 的服务器端版本和任何其他元数据 虽然有很多可用的客户端演示 但没有关于提取服务器元数据的内容 有人可以帮忙吗 请注意 我的客户端是远程 java 客户端 没有 had
  • 如何在 macOS 上以编程方式将文件和文件夹移至垃圾箱?

    我在这个主题上所能找到的只是提到FSMoveObjectToTrashSync函数 现在是已弃用并且没有列出替代方案 https developer apple com documentation coreservices 1566651
  • java xml 删除项目

    我有一个非常简单的 xml 文件 我想创建一个简单的函数来从中删除项目 这是我的 xml 文件
  • 为什么我们需要将压缩对象转换为列表

    我正在尝试完成一个数据营练习 其中我需要将 2 个列表转换为zip object然后进入一个dict最终得到一个dataframe使用熊猫 但是 如果我使用zip 对列表进行函数并将它们转换为字典 然后转换为数据框 我没有得到任何错误 但简
  • 如何检查 bash 脚本中是否以 root 身份运行

    我正在编写一个需要 root 级别权限的脚本 并且我想这样做 以便如果该脚本不以 root 身份运行 它只是回显 请以 root 身份运行 并退出 这是我正在寻找的一些伪代码 if whoami root then echo Please
  • 如何使用 Excel 在 Outlook 365 Exchange 中引用组或共享日历?

    我正在尝试让多个用户能够使用 Excel 将约会添加到共享日历 以下代码对我有用 我拥有共享日历 它位于 Outlook365 中的我的日历文件夹中 Sub CreateAppt Const olFolderCalendar 9 Const
  • 如何在 Dart 中创建一个空白的 Future + 如何返回当前正在进行的 Future?

    我正在尝试创建一个服务器端 Dart 类来执行各种与数据相关的任务 所有这些任务都依赖于首先初始化的数据库 问题是数据库的初始化是异步发生的 返回 Future 我首先尝试将初始化代码放入构造函数中 但放弃了这种方法 因为它似乎不可行 我现
  • 如何通过java代码在属性文件中写入值

    我有一个问题 我有一个属性文件 我想在该文件中存储一些值 并在需要时在代码中实现 有什么办法可以做到这一点吗 我在用Properties类来做到这一点 使用加载属性文件java util Properties http docs oracl
  • 为什么我无法将 firebase 电子邮件密码登录链接到 google 登录?

    我已经成功实施了Firebase Google 登录 https firebase google com docs auth android google signin在我的 Android 应用程序中 它工作正常 但是 我希望用户也使用电
  • 获取与 SIM 卡关联的电话号码

    如何获取与 CMDA 和 GSM 的 SIM 卡关联的电话号码以及服务提供商名称 Android TelephonyManager 可能不会在所有情况下都返回号码 如果运营商未设置号码 它可能不会返回号码 您必须创建一个验证场景 要求用户输
  • 如何向 Spark RDD 添加新列?

    我有一个 RDDMANY列 例如 hundreds 如何在此 RDD 的末尾添加一列 例如 如果我的 RDD 如下所示 123 523 534 893 536 98 1623 98472 537 89 83640 9265 7297 983
  • 更新(重新部署)现有的 azure webjob

    我创建了一个按需网络作业 在管理门户中 没有上传新 zip 或更新它的选项 我可以删除现有的网络作业并创建一个新的网络作业 但我想保留我的日志 有没有办法重新部署它 覆盖旧版本 维护日志 您可以通过 FTP 连接到 Webjob 所在的网站
  • 为什么 data-* 属性比普通 ID 属性更适合用于元素选择?

    Cypress https docs cypress io guides references best practices html Selecting Elements和许多其他关于测试 Web 应用程序的帖子建议依赖像这样的数据属性d
  • 原深感摄像头的拍摄范围是多少?

    前置原深感摄像头可以检测到的最小和最大距离是多少 When 检测深度数据 https developer apple com documentation avfoundation cameras and media capture stre
  • WPF - 延迟多重绑定

    我有一个多重绑定 看起来像这样