2010-02-10 33 views
17

Tôi có thể trì hoãn việc ràng buộc phần tử ui nếu phần tử hiện không hiển thị hay không. Đôi khi tôi có một biểu mẫu có một số yếu tố ẩn/thu nhỏ, tôi không muốn cập nhật chúng nếu chúng không có trên màn hình. Tôi nghi ngờ câu trả lời là không, nhưng nó không bao giờ đau để hỏi?WPF: Dừng ràng buộc nếu phần tử giao diện người dùng không hiển thị

+0

lý do tại sao bạn sẽ muốn làm điều đó? cho hiệu suất? –

+0

có hiệu suất, thực sự lười biếng của nó (lười biếng là mẹ của sáng chế) bởi vì tôi nên loại bỏ những thứ từ cây nếu họ không nhìn thấy được, để có được hiệu suất tôi cần. –

Trả lời

2

Không có cách nào được xây dựng để thực hiện việc này - nhưng bạn có thể tự viết nó.

Bí quyết là để quấn ràng buộc trong phần mở rộng đánh dấu riêng bạn mà sử dụng bản gốc ràng buộc nhưng thêm hành vi mới xung quanh nó (ví dụ, bằng cách thiết lập UpdateSourceTrigger để Explicit khi bạn không muốn ràng buộc để làm việc.

Dưới đây là một ví dụ (mà trì hoãn của truyền dữ liệu ràng buộc):

http://www.paulstovell.com/wpf-delaybinding

Giờ đây, có rất nhiều điều kiện cạnh có thể với việc vô hiệu hóa các ràng buộc cho các điều khiển vô hình, đặc biệt là xung quanh hiển thị và ẩn các điều khiển, vì vậy tôi sẽ không viết một phần mở rộng chung cho việc này - nhưng có thể trong ứng dụng cụ thể của bạn, điều này có thể hữu ích.

+1

thats wierd, tôi đã viết một điều tương tự - http://www.codeproject.com/KB/WPF/DelayedBindingTextBox.aspx –

7

Câu trả lời là không vì ràng buộc có thể là nguyên nhân khiến yếu tố hiển thị lại. Vì vậy, nếu ràng buộc đã không làm việc trên điều khiển ẩn nó sẽ không cho phép các ràng buộc để làm cho nó có thể nhìn thấy một lần nữa.

2

Để giải quyết sự cố, tôi có ràng buộc với khả năng hiển thị của đối tượng, khi đối tượng được đặt thành hiển thị, thuộc tính sẽ kích hoạt phần tử đằng sau đối tượng có liên kết qua ContentPresenter.

2

Tôi biết đây là một câu hỏi cũ, nhưng khi tôi không thể tìm thấy một lớp học được triển khai hoặc một cái gì đó, tôi đã tự mình làm theo câu trả lời @Nir.

Đây là một mở rộng Markup rằng kết thúc tốt đẹp bình thường ràng buộc để chỉ thực sự ràng buộc khi tài sản đối tượng IsVisible trở nên đúng đối với lần đầu tiên:

using System; 
using System.ComponentModel; 
using System.Globalization; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Markup; 

namespace MakupExtensions { 
    [MarkupExtensionReturnType(typeof(object))] 
    public class LazyBindingExtension : MarkupExtension { 
     public LazyBindingExtension() { 
     } 
     public LazyBindingExtension(PropertyPath path) : this() { 
      Path = path; 
     } 

     public IValueConverter Converter { 
      get; 
      set; 
     } 
     [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))] 
     public CultureInfo ConverterCulture { 
      get; 
      set; 
     } 
     public object ConverterParamter { 
      get; 
      set; 
     } 
     public string ElementName { 
      get; 
      set; 
     } 
     [ConstructorArgument("path")] 
     public PropertyPath Path { 
      get; 
      set; 
     } 
     public RelativeSource RelativeSource { 
      get; 
      set; 
     } 
     public object Source { 
      get; 
      set; 
     } 
     public UpdateSourceTrigger UpdateSourceTrigger { 
      get; 
      set; 
     } 
     public bool ValidatesOnDataErrors { 
      get; 
      set; 
     } 
     public bool ValidatesOnExceptions { 
      get; 
      set; 
     } 
     public bool ValidatesOnNotifyDataErrors { 
      get; 
      set; 
     } 

     private Binding binding; 
     private DependencyObject bindingTarget; 
     private DependencyProperty bindingTargetProperty; 

     public override object ProvideValue(IServiceProvider serviceProvider) { 
      var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
      if (valueProvider != null) { 
       bindingTarget = valueProvider.TargetObject as DependencyObject; 
       bindingTargetProperty = valueProvider.TargetProperty as DependencyProperty; 
       if (bindingTargetProperty == null || bindingTarget == null) { 
        throw new NotSupportedException($"The property '{valueProvider.TargetProperty}' on target '{valueProvider.TargetObject}' is not valid for a LazyBinding. The LazyBinding target must be a DependencyObject, and the target property must be a DependencyProperty."); 
       } 
       binding = new Binding { 
        Path = Path, 
        Converter = Converter, 
        ConverterCulture = ConverterCulture, 
        ConverterParameter = ConverterParamter 
       }; 
       if (ElementName != null) { 
        binding.ElementName = ElementName; 
       } 
       if (RelativeSource != null) { 
        binding.RelativeSource = RelativeSource; 
       } 
       if (Source != null) { 
        binding.Source = Source; 
       } 
       binding.UpdateSourceTrigger = UpdateSourceTrigger; 
       binding.ValidatesOnDataErrors = ValidatesOnDataErrors; 
       binding.ValidatesOnExceptions = ValidatesOnExceptions; 
       binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors; 
       return SetBinding(); 
      } 
      return null; 
     } 
     public object SetBinding() { 
      var uiElement = bindingTarget as UIElement; 
      if (uiElement != null && !uiElement.IsVisible) { 
       uiElement.IsVisibleChanged += UiElement_IsVisibleChanged; 
      } 
      else { 
       ConsolidateBinding(); 
      } 
      return bindingTarget.GetValue(bindingTargetProperty); 
     } 
     private void ConsolidateBinding() => BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding); 
     private void UiElement_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { 
      var uiElement = sender as UIElement; 
      if (uiElement != null && uiElement.IsVisible) { 
       uiElement.IsVisibleChanged -= UiElement_IsVisibleChanged; 
       ConsolidateBinding(); 
      } 
     } 
    } 
} 

Cách sử dụng:

<ItemsControl ItemsSource="{mx:LazyBinding Documents}"/> 

Trong ví dụ này, nó sẽ chỉ kết buộc khi ItemControl IsVisible trở thành sự thật cho lần đầu tiên.

Nó sẽ không hủy khi số IsVisible bị sai một lần nữa, nhưng tôi nghĩ ai đó có thể thay đổi nếu cần.

0

Cải tiến MarkupExtension bao bọc bình thường Ràng buộc vào mô hình dữ liệu tự động ràng buộc/hủy liên kết nếu có thể nhìn thấy được thay đổi.
Xem phiên bản trước here.

using System; 
using System.ComponentModel; 
using System.Globalization; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Markup; 

namespace UtilsWPF 
{ 
    [MarkupExtensionReturnType(typeof(object))] 
    public class LazyBindingExtension : MarkupExtension 
    { 
     public LazyBindingExtension() 
     { } 

     public LazyBindingExtension(PropertyPath path) : this() 
     { 
      Path = path; 
     } 

     #region Properties 

     public IValueConverter Converter { get; set; } 
     [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))] 
     public CultureInfo ConverterCulture { get; set; } 
     public object ConverterParamter { get; set; } 
     public string ElementName { get; set; } 
     [ConstructorArgument("path")] 
     public PropertyPath Path { get; set; } 
     public RelativeSource RelativeSource { get; set; } 
     public object Source { get; set; } 
     public UpdateSourceTrigger UpdateSourceTrigger { get; set; } 
     public bool ValidatesOnDataErrors { get; set; } 
     public bool ValidatesOnExceptions { get; set; } 
     public bool ValidatesOnNotifyDataErrors { get; set; } 

     private Binding binding; 
     private UIElement bindingTarget; 
     private DependencyProperty bindingTargetProperty; 

     #endregion 

     #region Init 

     public override object ProvideValue(IServiceProvider serviceProvider) 
     { 
      var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
      if (valueProvider != null) 
      { 
       bindingTarget = valueProvider.TargetObject as UIElement; 

       if (bindingTarget == null) 
       { 
        throw new NotSupportedException($"Target '{valueProvider.TargetObject}' is not valid for a LazyBinding. The LazyBinding target must be a UIElement."); 
       } 

       bindingTargetProperty = valueProvider.TargetProperty as DependencyProperty; 

       if (bindingTargetProperty == null) 
       { 
        throw new NotSupportedException($"The property '{valueProvider.TargetProperty}' is not valid for a LazyBinding. The LazyBinding target property must be a DependencyProperty."); 
       } 

       binding = new Binding 
       { 
        Path = Path, 
        Converter = Converter, 
        ConverterCulture = ConverterCulture, 
        ConverterParameter = ConverterParamter 
       }; 

       if (ElementName != null) 
       { 
        binding.ElementName = ElementName; 
       } 

       if (RelativeSource != null) 
       { 
        binding.RelativeSource = RelativeSource; 
       } 

       if (Source != null) 
       { 
        binding.Source = Source; 
       } 

       binding.UpdateSourceTrigger = UpdateSourceTrigger; 
       binding.ValidatesOnDataErrors = ValidatesOnDataErrors; 
       binding.ValidatesOnExceptions = ValidatesOnExceptions; 
       binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors; 

       return SetBinding(); 
      } 

      return null; 
     } 

     public object SetBinding() 
     { 
      bindingTarget.IsVisibleChanged += UiElement_IsVisibleChanged; 

      updateBinding(); 

      return bindingTarget.GetValue(bindingTargetProperty); 
     } 

     #endregion 

     #region Event Handlers 

     private void UiElement_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) 
     { 
      updateBinding(); 
     } 

     #endregion 

     #region Update Binding 

     private void updateBinding() 
     { 
      if (bindingTarget.IsVisible) 
      { 
       ConsolidateBinding(); 
      } 
      else 
      { 
       ClearBinding(); 
      } 
     } 

     private bool _isBind; 

     private void ConsolidateBinding() 
     { 
      if (_isBind) 
      { 
       return; 
      } 

      _isBind = true; 

      BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding); 
     } 

     private void ClearBinding() 
     { 
      if (!_isBind) 
      { 
       return; 
      } 

      BindingOperations.ClearBinding(bindingTarget, bindingTargetProperty); 

      _isBind = false; 
     } 

     #endregion 
    } 
} 

Cách sử dụng:

<ItemsControl ItemsSource="{utils:LazyBinding Documents}"/> 
Các vấn đề liên quan