WPF - 将转换器应用于所有文本框
问题描述:
使用WPF,我想在Text属性的Text属性的绑定内应用转换器。
单个文本框下面的工作:WPF - 将转换器应用于所有文本框
<TextBox Style="{StaticResource TextBoxStyleBase2}"
Text="{Binding Text, Converter={StaticResource MyConverter}}">
</TextBox>
然而,我们的文本框采用的是风格,控制模板,看起来像这样:
<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>
我如何申请使用该模板我的转换器? 谢谢!
答
试图修改从ControlTemplate
内TextBox
属性将是混乱的,所以我建议你在Style
而不是ControlTemplate
如果在所有可能做到这一点。我将首先解释如何使用Style
来解决该问题,然后解释如何在必要时使用该技术以便在ControlTemplate
中使用。
你需要做的是创造一个附加属性,可以这样使用:
<Style x:Name="TextBoxStyleBase2" TargetType="TextBox">
<Setter Property="local:ConverterInstaller.TextPropetyConverter"
Value="{StaticResource MyConverter}" />
...
</Style>
的ConverterInstaller
类有一个简单的附加属性,安装转换器转换成最初设定的TextBox
任何Binding
:
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完成加载并应用所有样式之后,并且
- 需要将绑定属性复制到新的绑定中以更改转换器,因为原始绑定是密封的
为了这个属性附加到控件模板中的元素,而不是在风格上做的,只是用传递到PropertyChangedCallback原来的对象相同的代码投var element = (FrameworkElement)obj;
和Dispatcher.BeginInvoke行动的实际文本框内与var box = (TextBox)element.TemplatedParent;
发现
非常感谢!这很好。我只需要修改新绑定的副本,因为Source和RelativeSource不能同时设置(即使它们被设置为NULL)。所以我在分配它们之前添加了一些检查。如果为NULL,我不设置属性。 – joerage 2010-06-07 17:08:12
感谢您的反馈。我已经更新了我的答案来做同样的事情。 – 2010-06-08 22:03:53