【问题标题】:Dependency Property Binding - Assign a new value依赖属性绑定 - 分配一个新值
【发布时间】:2012-02-01 10:27:08
【问题描述】:

我在我的 WPF 控件上实现了一个简单的 DependencyProperty,以便在 Binding 中使用它。

public static readonly DependencyProperty PollingProperty = DependencyProperty.Register("Polling", typeof(Polling), typeof(ConverterView), new UIPropertyMetadata(null));

public Polling Polling
{
    get { return (Polling)GetValue(PollingProperty); }
    set { SetValue(PollingProperty, value); }
}

控件本身设置为 DataContext,所以在 XAML 中我只是这样使用它:

<ProgressBar Height="25" Value="{Binding Path=Polling.Progress, Mode=OneWay}" />

Polling.Progress 是一个实现 INoftiyPropertyChanged 的​​整数属性,因此更改会被提升到 UI。一切正常,“进度”上的更改按预期显示在 ProgressBar 中。

但是,在我的应用程序中,有一个新的“轮询”实例应用于 DependencyProperty。

Polling = new Polling(); Polling.Start();

之后,不再评估绑定,ProgressBar 保持在旧实例的最后一个值。

更新:

由于我的情况可能有点具体,我会再解释一下。

我的 ConverterView WPF-Control 上的按钮允许用户开始操作:

private void cmdAusformatieren_Click(object sender, RoutedEventArgs e)
{
    Polling = Document.Converter(ConvertFinished);
}

Convert-method 将委托作为参数,将在操作完成后调用。 (整个过程异步运行。) Convert-Method 返回一个 Polling 对象,它提供了一个整数属性 Progress,它提供了我想在 ProgressBar 中显示的信息。 (这里可能会产生误导,Polling 是我的 DependencyProperty 的名称以及我的类的名称)。

就这一点而言,一切似乎都很好,并且绑定到 Polling.Progress 有效。

在第一个操作完成后触发的事件 ConvertFinished() 中,我得到一个新的 Polling 实例返回并希望从那时起在 Binding 中使用它。

private void ConvertFinished(object result)
{           
    Polling = Document.Format((byte[])result, FormatFinished);
}

对我的 Polling DependencyProperty 进行此分配后,Binding 不再更新并保持其先前的值。

【问题讨论】:

  • 我将其添加到答案中只是为了便于阅读。顺便说一句,您可以从 ConvertFinished 访问您的 UI 吗?
  • 是的,我回到了那里的 UI 线程,可以直接执行任何操作。
  • 强制 Progress 为 0 有效吗?
  • 在分配新值之前将其强制为 0 有效,是的。但是新实例在使用后,变化仍然不会出现。
  • 如果是粘性绑定,唯一摆脱的方法是使用数据源的深度克隆 - 您考虑过吗?

标签: c# wpf binding dependencies properties


【解决方案1】:

代替

Polling = new Polling () ;

你需要写

SetCurrentValue (PollingProperty, new Polling ()) ;

当您直接分配依赖属性时,其上的所有绑定都将丢失。 OTOH SetCurrentValue 不影响绑定,它只是设置当前值 (duh) 并传播通知。

【讨论】:

  • 这似乎有道理,但遗憾的是,它也不起作用。行为与以前相同。另外,我想避免在后面的代码中创建一个新的绑定。
  • 您是否将所有代码隐藏赋值重写为Polling(构造函数除外)以使用SetCurrentValue?我也不明白你需要在代码中创建什么绑定。
  • 我只需要分配,现在都使用 SetCurrentValue。在第一个之后一切正常(绑定是更新等),就像以前一样。我的确切代码行是:SetCurrentValue(PollingProperty, Document.Format((byte[])result, FormatFinished));
  • 您的意思是执行此行会删除绑定吗?那将是最不寻常的。我会在其上放置一个断点并在此行执行之前和之后检查绑定表达式(使用BindingExpression.GetBindingExpression (this, PollingProperty))。
【解决方案2】:

在这种情况下,最简单的解决方案是重新分配 binding,此时来自运行时的代码。原因,正如您也注意到的,绑定持有一个 reference 到它被 首先 分配的对象。

【讨论】:

  • @Dmitry:这是我从我的经验中注意到的
  • 有趣,不知怎的,我并不感到惊讶。但这非常糟糕,因为使用“粘性”绑定显示的值可能是错误的!我自己没见过,但如果它存在的话,它绝对是 WPF 中最严重的错误之一。
  • 重新分配绑定在 99.9% 的情况下都是错误的解决方案。使用SetCurrentValue!
  • @Tigran 同意,我之前也遇到过同样的问题。或者如果 Polling 类是由您实现的,您可以添加 reset 方法以重置回初始状态。所以你不必重新分配绑定。
【解决方案3】:

好的,你可以试试这个:

BindingOperations.ClearBinding(this.YouProgressBarName, ProgressBar.ValueProperty); BindingOperations.SetBinding(this.YouProgressBarName, ProgressBar.ValueProperty);

首先检查它是否有效。我预计不会。

我建议更改一件事 - 摆脱子属性(我知道您使用复杂对象来减少 dels 中的参数数量)。他们对 WPF 框架的支持有限。

我要尝试的另一件事是在为它分配新值之前将 Polling 属性值强制为 0

private void cmdAusformatieren_Click(object sender, RoutedEventArgs e)
{
    this.Polling.Progress = 0; // see if make any difference
    this.Polling = Document.Converter(ConvertFinished);

    if (this.Polling.Progress != 0) { throw new Exception(); }
}

【讨论】:

  • 第一次设置轮询实例,在单击 ConverterView 上的按钮后。一切正常,直到另一个事件创建一个新的轮询实例并将其分配给 DP。
  • @Roper 你能发布那个事件处理程序的代码吗? 'Path=Polling.Progress' 意味着 Polling 是一个属性,而 'Polling = new Polling();轮询.Start();'说这是别的东西;)
  • @Roper 您能否发布代码的简化版本作为您问题的更新?此外,当大量“mandelbugs”是由异步调用引起的 - 你可以同步运行你的操作来消除这种可能性吗?
  • 好的,我已经更新了我上面的问题。对不起,我之前评论中的糟糕代码格式。由于该操作最多需要几分钟,因为网络上的 WebServices 和其他机器发生了很多事情,所以它必须是异步的。
猜你喜欢
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 2012-08-26
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多