【问题标题】:how to intercept WPF binding for custom processing如何拦截 WPF 绑定以进行自定义处理
【发布时间】:2011-01-21 14:34:25
【问题描述】:

假设您有一个窗口,上面有 20 个文本框,它们都绑定到不同的 BLL 类。与 wpf 绑定时,如何拦截从文本框传递到属性的值?我正在寻找一个通用的解决方案,而不是为每个属性都这样做。

我可以从 Binding 类继承,但是当数据从 uielement 传递到属性时,我可以在该类中监听一个事件吗?还是有更好的解决方案?

【问题讨论】:

    标签: .net binding


    【解决方案1】:

    Binding 有一个 Converter 属性,您可以将一个实现 IValueConverter 的类分配给该属性。如果您可以从绑定继承,也许您可​​以将 Converter 设置为该专业化并继续。

    【讨论】:

    • 与 mattythomas2000 的评论相同:是的,但我已经有很多 valueconverters 可以做各种事情。通过自定义绑定类设置 valueconverter 将清除这些。绑定类中不是有简单的更新事件吗?
    • 在这种情况下,您可能想要设计一个复合 IValueConverter...不知道在组合值修改时要实现什么样的逻辑,但是您可以轻松地拥有一个可以合并多个值的 IValueConverter 实现转换器合二为一
    【解决方案2】:

    我认为您正在寻找的解决方案是价值转换器。此 msdn 页面描述了如何执行此操作 -> http://msdn.microsoft.com/en-us/library/ms752347.aspx#data_conversion

    【讨论】:

    • 是的,但我已经有很多 valueconverters 可以做各种各样的事情。通过自定义绑定类设置 valueconverter 将清除这些。绑定类中不是有简单的更新事件吗?
    • 如果它们都实现相同的逻辑(使用 flq 建议的某种复合 IValueConverter),您应该能够将值转换器存储在资源中并为每个绑定重新使用它。
    【解决方案3】:

    我可能弄错了,但您是否尝试过使用转换器?这是一个不错的网站,你可以看看:

    http://www.switchonthecode.com/tutorials/wpf-tutorial-binding-converters

    【讨论】:

    • 与 mattythomas2000 的评论相同:是的,但我已经有很多 valueconverters 可以做各种事情。通过自定义绑定类设置 valueconverter 将清除这些。绑定类中不是有简单的更新事件吗?
    • 不明白为什么价值转换器不是最好的方法?你的xaml中有一堆文本框..它们绑定到某个viewModel或类似的东西..你想做什么?主要目标是什么?为什么价值转换器不是合适的解决方案?
    【解决方案4】:

    我想对所有三个答案都进行投票,但我没有这方面的声誉。投票给这个,我会投票给你;)

    感谢你们,我解决了我的问题!

    这就是我所做的:

    1. 创建一个带有事件 SourceUpdated 的新 ValueConverter,只要有一个值通过它就会触发。
    2. 从中继承我们现有的所有转换器。
    3. 新建一个Binding类(继承自Binding),在构造函数中查看是否已经有Converter,如果没有则创建:

      if (Converter == null) {
          Converter = new GcBindingConverter();
      }
      
      if (Converter.GetType().IsAssignableFrom(typeof(GcBindingConverter))) {
          ((GcBindingConverter)Converter).SourceUpdated += SourceUpdatedHandler;
      }
      
    4. 在需要此功能的每个表单上,将事件连接到事件处理程序,我已将处理程序放在我们的模型状态中:

      static void WireDirtyBindings(DependencyObject element, ModelStateBase ModelState)
      {
          Binding bb = null;
          // find bindings on elements:
          if ((object.ReferenceEquals(element.GetType, typeof(TextBox)))) {
              bb = BindingOperations.GetBinding(element, TextBox.TextProperty);
          } else if ((object.ReferenceEquals(element.GetType, typeof(ComboBox)))) {
              bb = BindingOperations.GetBinding(element, ComboBox.SelectedValueProperty);
              // other objects...
          }
      
      
      if (bb != null) {
          // wire eventhandler to event:
          doWireHandler(bb, ModelState);
      }
      
      // Now, recurse through any child elements
      if (element is FrameworkElement || element is FrameworkContentElement) {
          foreach (object childElement in LogicalTreeHelper.GetChildren(element)) {
              if (childElement is DependencyObject) {
                  WireDirtyBindings((DependencyObject)childElement, ModelState);
              }
          }
      }
      

      }

    对于每个有大量数据输入的表单,我现在唯一需要写的是:

    BaseBinding.WireDirtyBindings(this, _modelState);
    

    5:在表单中,将 save changes 按钮的启用状态绑定到表示是否有任何更改的 modelstate 属性。我也可以为此使用一个接口,但因为我们已经有了类似模型状态的东西,所以这是一个放置它的好地方。

    只需几行代码就可以很好地工作。现在我不必担心最终用户会进行大量更改而不保存。

    【讨论】:

      猜你喜欢
      • 2017-03-20
      • 2022-07-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 2020-03-01
      相关资源
      最近更新 更多