DataContext更改时立即更新绑定 [英] Updating Binding immediately when DataContext changes

查看:78
本文介绍了DataContext更改时立即更新绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在更改DataContext之后立即测量一个对象,但是该对象的绑定不会很快更新。这是我的代码:

I am trying to measure an object immediately after changing the DataContext, but the binding for the object is not getting updated soon enough. Here's my code:

// In MeasureOverride(Size)
m_inputWidth = 0.0;

Size elemSize = new Size(double.PositiveInfinity, RowHeight);
MapElementView ruler = new MapElementView();

// Measure inputs
foreach (MapElementViewModel elem in m_vm.InputElements)
{
   ruler.DataContext = elem;
   ruler.Measure(elemSize);
   m_inputWidth = Math.Max(m_inputWidth, ruler.DesiredSize.Width);
}

我希望更新View对象的绑定,以便我可以测量如何大的View需要显示ViewModel。我正在重复使用相同的视图进行测量,因为我正在虚拟化数据。

I want the bindings for the View object to update so that I can measure how large the View needs to be to display the ViewModel. I am reusing the same View to measure because I am virtualizing the data.

有没有人知道如何在DataContext更改时强制更新绑定?

Does anyone know how to force the binding to update when the DataContext changes?

请注意,绑定确实会更新。

Note that the binding does update eventually.

该视图包含一个TextBlock,它是基于ViewModel更改大小的主要元素。在更改DataContext之后,我已经看到了这个元素上的TextProperty的BindingExpression,但调用UpdateTarget()并不能解决问题,而BindingExpression.DataItem看起来是空的。

The View contains a TextBlock that is the main element that changes size based on the ViewModel. I have looked at the BindingExpression for the TextProperty on this element immediately after changing the DataContext, but calling UpdateTarget() does not fix the problem and BindingExpression.DataItem appears to be null.

编辑:
BindingExression的状态为Unattached。诀窍是找出如何附加它。

The status of the BindingExression is Unattached. The trick is to figure out how to attach it.

推荐答案

嗯,如果在设置DataContext之后,你在调度器在DataBind优先级,它应该导致所有的更新。

Well, if after setting the DataContext, you did an Invoke on the Dispatcher at the DataBind priority, it should cause them all to be updated.

由于此代码正在MeasureOverride方法中执行,您不能在调度员相反,我会做一个标志,指示如果标尺宽度已经被测量,如果不是,则在计算这些宽度的方法上做一个BeginInvoke。然后,当计算宽度时,调用InvalidateMeasure强制进行第二个布局传递。

Since this code is being executed inside the MeasureOverride method, you can't do an Invoke on the Dispatcher. Instead, I would make a flag that indicated if the ruler width had been measured, and if not, do a BeginInvoke on the method that calculates those widths. Then, when the widths are calculated, call InvalidateMeasure to force a second layout pass.

每当这些宽度之一变化时,这将需要额外的布局传递。您需要在需要重新设置文本框时将该标志重置为false。

This is going to require an additional layout pass every time one of those widths changes. You will need to reset the flag to false whenever the textboxes have to be remeasured.

private bool isRulerWidthValid = false;

protected override Size MeasureOverride(Size available)
{
    ... // other code for measuring
    if (!isRulerWidthValid)
    { 
        Dispatcher.BeginInvoke(new Action(CalculateRulerSize));
        ... // return some temporary value here
    }

    ... // do your normal measure logic
}

private void CalculateRulerSize(Size available)
{
    Size elemSize = new Size(double.PositiveInfinity, RowHeight);
    m_inputWidth = 0.0;

    foreach (MapElementViewModel elem in m_vm.InputElements)
    {
       ruler.DataContext = elem;
       ruler.Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.DataBind);
       ruler.Measure(elemSize);
       m_inputWidth = Math.Max(m_inputWidth, ruler.DesiredSize.Width);
    }

    // invalidate measure again, as we now have a value for m_inputwidth
    isRulerWidthValid = true;
    InvalidateMeasure();
}

这篇关于DataContext更改时立即更新绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆