2010-02-10 3 views
17

Puis-je différer la liaison d'un élément d'interface utilisateur si l'élément n'est pas visible actuellement? Parfois, j'ai une forme qui a des éléments cachés/réduits au minimum, je voudrais de ne pas les mettre à jour si elles ne sont pas à l'écran. Je soupçonne que la réponse est non, mais ça ne fait jamais de mal de demander? La réponse est non, car la liaison peut être la cause de la réapparition d'un élément.WPF: Arrêter la liaison si un élément d'interface utilisateur n'est pas visible

+0

pourquoi voudriez-vous faire cela? pour la performance? –

+0

performance oui, sa paresse fait (la paresse est la mère de l'invention) parce que je dois supprimerons les choses de l'arbre si elles ne coûtent pas visibles, pour obtenir la performance que j'ai besoin. –

Répondre

2

Il n'y a pas de façon intégrée de le faire - mais vous pouvez l'écrire vous-même.

L'astuce consiste à envelopper la liaison dans votre propre extension de balisage qui utilise la liaison d'origine, mais ajoute un nouveau comportement autour d'elle (par exemple, en mettant UpdateSourceTrigger Explicite lorsque vous ne voulez pas la liaison au travail.

Voici un exemple (qui retarde le transfert de données de la liaison):

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

maintenant, il y a beaucoup de conditions de pointe possibles avec la désactivation des liaisons pour les contrôles invisibles, en particulier autour de l'affichage et des contrôles cacher, donc je ne écrire une extension générique pour cela - mais peut être dans votre application spécifique cela peut être utile.

+1

des thats wierd, je l'ai écrit une chose similaire - http://www.codeproject.com/KB/WPF/DelayedBindingTextBox.aspx –

7

La réponse est non. Donc, si la liaison ne fonctionne pas sur les contrôles cachés, elle ne permettra pas à la liaison de la rendre à nouveau visible.

2

Pour une solution de contournement j'ai une liaison à la visibilité de l'objet, lorsque l'objet est mis à visible, la propriété déclenche la construction de l'élément derrière lui qui ont une liaison via un ContentPresenter.

2

Je sais que c'est une vieille question, mais comme je n'ai pas réussi à trouver une classe implémentée ou quelque chose, je l'ai fait moi-même, en suivant la réponse de @Nir.

Ceci est une extension de balisage qui enveloppe de liaison normale à ne lier vraiment lorsque l'objet IsVisible propriété devient vrai pour la première fois:

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

Pour utiliser:

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

Dans cet exemple, il se liera que lorsque le ItemsControl IsVisible devient vrai pour la première fois.

Il ne sera pas dissocié lorsque le IsVisible se trompe à nouveau, mais je pense que quelqu'un peut le changer au besoin.

0

Amélioration de MarkupExtension qui enveloppe la liaison normale au modèle de données de liaison/dissociation automatique si elle est modifiée.
Voir version précédente 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 
    } 
} 

Pour utiliser:

<ItemsControl ItemsSource="{utils:LazyBinding Documents}"/> 
Questions connexes