2009-03-19 7 views
9

DataContext를 변경 한 직후에 개체를 측정하려고하는데 개체 바인딩이 곧 업데이트되지 않습니다.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); 
} 

내가보기 개체 내가보기 뷰 모델을 표시 할 필요가 얼마나 큰지 측정 할 수 있도록 업데이트 할 바인딩을 원하는 : 여기에 내 코드입니다. 내가 데이터를 가상화하기 때문에 측정을 위해 동일한 뷰를 재사용하고 있습니다.

누구든지 DataContext가 변경 될 때 바인딩을 강제로 업데이트하는 방법을 알고 있습니까?

결국 바인딩이 업데이트됩니다.

보기에는 ViewModel을 기준으로 크기를 변경하는 주요 요소 인 TextBlock이 포함되어 있습니다. DataContext를 변경 한 직후에이 요소의 TextProperty에 대한 BindingExpression을 살펴 봤지만 UpdateTarget()을 호출해도 문제가 해결되지 않고 BindingExpression.DataItem이 null로 표시됩니다.

편집 : BindingExression의 상태는 연결 해제입니다. 트릭은 연결 방법을 알아내는 것입니다.

답변

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(); 
} 
+0

좋은 아이디어. 나는 그것을 시도 할 것이다. –

+0

다음 예외가 발생합니다. 디스패처 처리가 일시 중단 된 동안이 작업을 수행 할 수 없습니다. WPF가 레이아웃 중에 Dispatcher를 잠그는 것처럼 보입니다. MeasureOverride()에서이 코드를 실행하면 –

관련 문제