2010-05-31 3 views
2

En utilisant WPF, je souhaite appliquer un convertisseur dans la liaison de la propriété Text dans tous mes TextBox.
Les travaux suivants pour une seule zone de texte:WPF - Appliquer un convertisseur à toutes les zones de texte

<TextBox Style="{StaticResource TextBoxStyleBase2}" 
          Text="{Binding Text, Converter={StaticResource MyConverter}}"> 
        </TextBox> 

Cependant, nos TextBoxes utilise un style avec un modèle de contrôle qui ressemble à ceci:

<Grid> 
      <Border x:Name="Border" 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}" 
        CornerRadius="{StaticResource DefaultCornerRadius}"> 
       <Grid> 
        <Border BorderThickness="1"> 
         <ScrollViewer x:Name="PART_ContentHost" Margin="0"/> 
        </Border> 
       </Grid> 
      </Border> 
     </Grid> 

Comment puis-je appliquer mon convertisseur en utilisant ce modèle? Merci!

Répondre

2

Toute tentative de modifier TextBox propriétés de l'intérieur du ControlTemplate sera en désordre, donc je vous recommande de le faire dans le Style au lieu du ControlTemplate si possible. Je vais commencer par expliquer comment le faire avec un Style puis expliquer comment adapter la technique pour l'utiliser dans un ControlTemplate si nécessaire.

Ce que vous devez faire est de créer une propriété attachée qui peut être utilisé comme ceci:

<Style x:Name="TextBoxStyleBase2" TargetType="TextBox"> 
    <Setter Property="local:ConverterInstaller.TextPropetyConverter" 
      Value="{StaticResource MyConverter}" /> 
    ... 
</Style> 

La classe ConverterInstaller a simple propriété jointe qui installe le convertisseur dans une Binding initialement fixé sur le TextBox:

public class ConverterInstaller : DependencyObject 
{ 
    public static IValueConverter GetTextPropertyConverter(DependencyObject obj) { return (IValueConverter)obj.GetValue(TextPropertyConverterProperty); } 
    public static void SetTextPropertyConverter(DependencyObject obj, IValueConverter value) { obj.SetValue(TextPropertyConverterProperty, value); } 
    public static readonly DependencyProperty TextPropertyConverterProperty = DependencyProperty.RegisterAttached("TextPropertyConverter", typeof(IValueConverter), typeof(Converter), new PropertyMetadata 
    { 
    PropertyChangedCallback = (obj, e) => 
     { 
     var box = (TextBox)obj; 
     box.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => 
      { 
      var binding = BindingOperations.GetBinding(box, TextBox.TextProperty); 
      if(binding==null) return; 

      var newBinding = new Binding 
      { 
       Converter = GetTextPropertyConverter(box), 

       Path = binding.Path, 
       Mode = binding.Mode, 
       StringFormat = binding.StringFormat, 
      } 
      if(binding.Source!=null) newBinding.Source = binding.Source; 
      if(binding.RelativeSource!=null) newBinding.RelativeSource = binding.RelativeSource; 
      if(binding.ElementName!=null) newBinding.ElementName = binding.ElementName; 

      BindingOperations.SetBinding(box, TextBox.TextProperty, newBinding); 
      })); 
     } 
    }); 
} 

La seule complexité est ici:

  • L'utilisation de Dispatcher.BeginInvoke pour s'assurer que la mise à jour de liaison se produit après le chargement du XAML et tous les styles sont appliqués, et
  • La nécessité de copier les propriétés de liaison dans une nouvelle liaison pour changer le convertisseur, puisque la liaison d'origine est scellée

pour fixer cette propriété à un élément à l'intérieur du ControlTemplate au lieu de le faire dans le style, le même code est utilisé, sauf l'objet d'origine dans le passé PropertyChangedCallback est jeté var element = (FrameworkElement)obj; et à l'intérieur de l'action Dispatcher.BeginInvoke la zone de texte réelle est trouvé avec var box = (TextBox)element.TemplatedParent;

+0

Un grand merci! Cela a bien fonctionné. J'ai seulement dû modifier la copie de la nouvelle liaison puisque, Source et RelativeSource ne peuvent pas tous les deux être placés en même temps (même s'ils ont la valeur NULL). J'ai donc ajouté quelques vérifications avant de les attribuer. Si NULL, je ne définis pas la propriété. – joerage

+0

Merci pour les commentaires. J'ai mis à jour ma réponse pour faire la même chose. –

Questions connexes