【问题标题】:Updating Binding immediately when DataContext changes当 DataContext 发生变化时立即更新 Binding
【发布时间】:2009-03-19 16:18:36
【问题描述】:

我试图在更改 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。我正在重复使用相同的视图进行测量,因为我正在虚拟化数据。

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

请注意,绑定最终会更新。

View 包含一个 TextBlock,它是根据 ViewModel 改变大小的主要元素。在更改 DataContext 后,我​​立即查看了此元素上 TextProperty 的 BindingExpression,但调用 UpdateTarget() 并不能解决问题,并且 BindingExpression.DataItem 似乎为空。

编辑: BindingExression 的状态是未附加。诀窍是弄清楚如何附加它。

【问题讨论】:

    标签: c# .net wpf data-binding


    【解决方案1】:

    好吧,如果在设置 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();
    }
    

    【讨论】:

    • 我收到以下异常:调度程序处理暂停时无法执行此操作。似乎 WPF 在布局期间锁定了 Dispatcher。我在 MeasureOverride() 中运行此代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多