2009-03-19 50 views
9

Tôi đang cố gắng đo một đối tượng ngay sau khi thay đổi DataContext, nhưng ràng buộc cho đối tượng không được cập nhật sớm đủ. Đây là mã của tôi:Cập nhật Binding ngay lập tức khi DataContext thay đổi

// 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); 
} 

Tôi muốn các ràng buộc cho đối tượng Xem cập nhật để tôi có thể đo mức độ lớn mà Chế độ xem cần hiển thị ViewModel. Tôi đang tái sử dụng cùng một Chế độ xem để đo lường vì tôi đang ảo hóa dữ liệu.

Có ai biết cách buộc ràng buộc để cập nhật khi DataContext thay đổi không?

Lưu ý rằng liên kết sẽ cập nhật cuối cùng.

Chế độ xem chứa TextBlock là thành phần chính thay đổi kích thước dựa trên ViewModel. Tôi đã xem BindingExpression cho TextProperty trên phần tử này ngay lập tức sau khi thay đổi DataContext, nhưng gọi UpdateTarget() không khắc phục được sự cố và BindingExpression.DataItem dường như là rỗng.

EDIT: Trạng thái của BindingExression là Unattached. Bí quyết là tìm ra cách đính kèm nó.

Trả lời

5

Vâng, nếu sau khi thiết lập DataContext, bạn đã thực hiện một lời gọi trên Dispatcher ở mức ưu tiên DataBind, nó sẽ làm cho tất cả chúng được cập nhật.

Vì mã này đang được thực thi bên trong phương pháp MeasureOverride, bạn không thể thực hiện một Lệnh trên Trình điều phối. Thay vào đó, tôi sẽ làm cho một lá cờ chỉ ra nếu chiều rộng thước đo đã được đo, và nếu không, làm một BeginInvoke trên phương pháp tính toán chiều rộng. Sau đó, khi độ rộng được tính toán, hãy gọi InvalidateMeasure để ép buộc bố cục thứ hai vượt qua.

Điều này sẽ yêu cầu bố cục bổ sung vượt qua mỗi lần một trong những độ rộng đó thay đổi. Bạn sẽ cần đặt lại cờ thành sai bất cứ khi nào các hộp văn bản phải được chỉnh sửa lại.

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

Ý tưởng hay. Tôi sẽ thử xem. –

+0

Tôi nhận được ngoại lệ sau: Không thể thực hiện thao tác này trong khi xử lý điều phối bị tạm ngưng. Có vẻ như WPF khóa Dispatcher trong khi bố trí. Tôi chạy mã này trong MeasureOverride() –

Các vấn đề liên quan