【问题标题】:Set NotifyOnTargetUpdated for existing binding为现有绑定设置 NotifyOnTargetUpdated
【发布时间】:2021-09-22 16:48:30
【问题描述】:

我在 xaml <TextBlock Style="{StaticResource textStyle}" Text="{Binding DisplayText}" /> 中有一个绑定。

我正在尝试编写一个附加的行为来响应绑定的DisplayText 值的变化。如果我在 xaml 中指定 NotifyOnTargetUpdated=True,我可以对行为中的更改做出反应,一切都很好,但我宁愿不依赖于以特定方式绑定 Text 属性只是为了使行为起作用。

我的想法是在选择加入行为时更改现有 TextBlock.TextProperty 绑定上的 NotifyOnTargetUpdated 值。我正在使用以下代码执行此操作,其中 tb 是选择加入的 TextBlock。

var textBinding = BindingOperations.GetBinding(tb, TextBlock.TextProperty);
textBinding.NotifyOnTargetUpdated = true;
tb.SetBinding(TextBlock.TextProperty, textBinding);

行为是这样选择的,样式如下: <Setter Property="behaviors:Text.AutoSizeText" Value="True"/>

最初这不起作用,因为textBinding 为空。我可以通过在行为属性之前在 xaml 中绑定 Text 属性来解决这个问题,但这仍然会留下我不喜欢的外部依赖项(xaml 排序)。如果我确实走这条路,我会得到以下异常,这似乎表明我根本无法以这种方式完成。

InvalidOperationException: Binding cannot be changed after it has been used.

那么,我该如何自动处理设置notifyOntArgetUpdupdupdupdupd the Text binding当行为被选择时?

【问题讨论】:

  • 我已经添加了行为的用法,但我不确定你对绑定 DisplayText 的意思 - 我在上面的 TextBlock xaml 中绑定了它。
  • 我不确定是否有明智的方法来做到这一点...您可以拥有一个单独的属性来绑定,例如my:Stuff.Text="{Binding DisplayText}" 而不是绑定到 Text,这会让您默认绑定到 NotifyOnTargetUpdated = true
  • 您建议使用内部Text 属性,该属性与TextBlock.TextProperty 绑定绑定到相同的目标,该属性是在正确设置NotifyOnTargetUpdated 值的代码中创建的。我相信这可行,谢谢。
  • 是的,它必须在后台转发到TextProperty,但它只是暴露了一个默认值略有不同的绑定。这仍然很丑陋,并且仍然很容易绑定到错误的属性,但是嘿,这是一个选项
  • 也许我有些不明白,但 NotifyOnTargetUpdated 会打开有关 TextBlock.Text 更改的通知,而不是 DataContext.DisplayText。因此,您观看的不是 DisplayText,而是 Text。如果是这样,为什么不让 gording 更容易:绑定到 TextBlock.Text 属性。使用一个 DependecyProperty 创建一个内部 DependecyObject 并将其绑定到 TextBlock.Text。

标签: c# wpf attachedbehaviors


【解决方案1】:

感谢@canton7 提供的指导,我能够解决我的问题。我最初(通常情况下)是在寻找实现我想象中的解决方案的方法,而不是寻找适合我需要的解决方案。调整我的前景后,我的工作解决方案是:

将 AttachedProperty InternalText 添加到行为类,并使用属性更改处理程序。

private static readonly DependencyProperty InternalTextProperty = DependencyProperty.RegisterAttached(
            "InternalText", typeof(string), typeof(Text), new PropertyMetadata(default(string), HandleInternalTextChanged));

如果我最初设置NotifyOnTargetUpdated 的想法成功的话,在更改后的处理程序(上面的HandleInternalTextChanged)中执行我会在TargetUpdated 处理程序中完成的工作。

在选择加入我的行为时,创建从选择加入的 TextBlock.TextInternalText 附加属性的绑定。

var internalBinding = new Binding { Source = tb, Path = new PropertyPath(TextBlock.TextProperty) };
tb.SetBinding(InternalTextProperty, internalBinding);

InternalTextProperty 上的 HandleInternalTextChanged 回调允许我通过提供另一种通知每次更改的方法来解决无法更改 NotifyOnTargetUpdated 值的问题。

【讨论】:

    【解决方案2】:

    我更喜欢在内部绑定到 DisplayText,因为如果可能的话,我更喜欢绑定到源,而不是通过 TextBlock.Text 属性进行菊花链。

    如果您需要绑定到源属性,那么它的创建方式会略有不同。

        var binding =  BindingOperations.GetBindingBase(tb, TextBox.TextProperty);
        if (binding == null)
        {
            tb.ClearValue(InternalTextProperty);
        }
        else
        {
            tb.SetBinding(InternalTextProperty, binding);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-04
      • 2010-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-19
      • 2016-05-21
      • 1970-01-01
      相关资源
      最近更新 更多