2010-05-31 2 views
2

Используя WPF, я хочу применить конвертер в привязке свойства Text во всех моих текстовых блоках.
следующие работы для одного TextBox:WPF - применить конвертер ко всем текстовым полям

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

Однако наши TextBoxes использует стиль с шаблоном управления, который выглядит следующим образом:

<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> 

Как я могу применить мой преобразователь, используя этот шаблон? Спасибо!

ответ

2

Любая попытка изменить TextBox свойства из внутри ControlTemplate будет грязным, поэтому я рекомендую вам сделать это в Style вместо ControlTemplate, если вообще возможно. Я начну с объяснения, как это сделать с помощью Style, а затем объясните, как при необходимости адаптировать технику для использования в ControlTemplate.

Что вам нужно сделать, это создать вложенное свойство, которое может использоваться как это:

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

ConverterInstaller класса имеет простое вложенное свойство, которое устанавливает преобразователь в любой Binding первоначально установленный на 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); 
      })); 
     } 
    }); 
} 

Единственная сложность здесь:

  • Использование Dispatcher.BeginInvoke для обеспечения обновления привязки происходит после завершения загрузки XAML и всех стилей, и
  • Необходимость скопировать свойства связывания в новую привязку для изменения конвертера, поскольку оригинальное связывание закрыто

чтобы прикрепить это свойство к элементу внутри ControlTemplate вместо того, чтобы делать это в стиле, и тот же код используется, за исключением исходного объекта, переданного в PropertyChangedCallback отливают var element = (FrameworkElement)obj; и внутри действия Dispatcher.BeginInvoke фактическое TextBox находится с var box = (TextBox)element.TemplatedParent;

+0

Большое спасибо! Это отлично поработало. Я только должен был изменить копию новой привязки, поскольку Source и RelativeSource не могут быть установлены одновременно (даже жесткие они установлены в NULL). Поэтому я добавил некоторые проверки перед их назначением. Если NULL, я не устанавливаю свойство. – joerage

+0

Спасибо за отзыв. Я обновил свой ответ, чтобы сделать то же самое. –