2010-02-10 2 views
17

Могу ли я задержать привязку элемента ui, если элемент в настоящее время не виден. Иногда у меня есть форма, в которой есть скрытые/минимизированные элементы, я бы не хотел их обновлять, если они не отображаются на экране. Я подозреваю, что ответ отрицательный, но никогда не больно спрашивать?WPF: остановить привязку, если элемент пользовательского интерфейса не отображается

+0

почему вы хотите сделать это? для производительности? –

+0

да исполнение, его на самом деле лень (лень - мать изобретения), потому что я должен удалять вещи из дерева, если они не видны, чтобы получить нужную мне производительность. –

ответ

2

Нет встроенного способа сделать это, но вы можете написать его самостоятельно.

Хитрость заключается в том, чтобы обернуть связывание в собственной внутренней линии разметки, который использует оригинальный переплет, но добавляет новое поведение вокруг него (например, путем установки UpdateSourceTrigger в Явный, когда вы не хотите связывание работать.

Вот пример (который задерживает передачу связывающей свои данных):

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

Теперь, есть много возможных условия краев с отключением привязок для невидимых элементов управления, особенно вокруг, показывая и скрывая элементы управления, так что я бы не стал напишите общее расширение для этого, но можете быть в вашем конкретном приложении, это может быть полезно.

+1

thats wierd, я написал аналогичную вещь - http://www.codeproject.com/KB/WPF/DelayedBindingTextBox.aspx –

7

Ответ отрицательный, потому что привязка может быть причиной повторного создания элемента. Поэтому, если привязка не работает с скрытыми элементами управления, это не позволит привязке сделать ее видимой снова.

2

Для обходного пути у меня есть привязка к видимости объекта, когда объект установлен на видимый, свойство запускает конструкцию элемента позади него, который имеет привязку через ContentPresenter.

2

Я знаю, что это старый вопрос, но поскольку я не смог найти реализованный класс или что-то еще, я сделал это сам, следуя @Nir ответу.

Это расширение разметки, который оборачивает нормальное связывание только действительно связывается, когда свойство объекта IsVisible становится истинным в первый раз:

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

Применение:

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

В этом примере, он будет привязываться только тогда, когда ItemControl IsVisible станет истинным в первый раз.

Он не отцепляется, когда IsVisible снова получает ложную информацию, но я думаю, что кто-то может поменять его по мере необходимости.

0

Улучшенная MarkupExtension, которая обертывает нормальную привязку к автоматической привязке/развязыванию модели данных, если видимая изменена.
См. Предыдущую версию 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 
    } 
} 

Применение:

<ItemsControl ItemsSource="{utils:LazyBinding Documents}"/> 
Смежные вопросы