我正在尝试在更改DataContext后立即测量对象,但对象的绑定不会很快得到更新。这是我的代码:
// 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所需的大小。我正在重复使用相同的View来衡量,因为我正在虚拟化数据。
有人知道如何在DataContext更改时强制绑定更新吗?
请注意,绑定最终会更新。
View包含一个TextBlock,它是根据ViewModel更改大小的主要元素。我在更改DataContext后立即查看了此元素上的TextProperty的BindingExpression,但调用UpdateTarget()并不能解决问题,BindingExpression.DataItem似乎为null。
编辑: BindingExression的状态是Unattached。诀窍是弄清楚如何附加它。
答案 0 :(得分:5)
好吧,如果在设置DataContext之后,你在DataBind优先级的Dispatcher上进行了一次Invoke,它应该使它们全部更新。
由于此代码正在MeasureOverride方法内执行,因此您无法在Dispatcher上执行Invoke。相反,我会制作一个标志,指示是否已经测量了标尺宽度,如果没有,则在计算这些宽度的方法上执行BeginInvoke。然后,在计算宽度时,调用InvalidateMeasure以强制执行第二次布局。
每当其中一个宽度发生变化时,就需要额外的布局传递。每当必须重新测量文本框时,您需要将标志重置为false。
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();
}