如果我通过自定义控件中的依赖项属性传输绑定,则不会显示验证错误。
详细信息
我有一个视图模型,该视图模型总是对一个属性存在验证错误
class ViewModel : IDataErrorInfo
{
public string Value { get; set; }
public string Error
{
get { return null; }
}
public string this[string columnName]
{
get { return "Error"; }
}
}
和观看中的TextBox
<TextBox
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />
所以它将被红色边框包围。
然后我创建了一个名为WrappedTextBox
的自定义控件,其中包含一个Text
依赖属性
class WrappedTextBox : Control
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(WrappedTextBox));
}
和模板
<Style TargetType="local:WrappedTextBox">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:WrappedTextBox">
<Grid>
<AdornerDecorator>
<TextBox
Text="{Binding Text,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True,
RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
将其放在视图上
<local:WrappedTextBox
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />
如上图所示,第二个控件上没有红色边框。
如果我不删除Validation.ErrorTemplate
中的WrappedTextBox
,它将是
如何在TextBox
内的WrappedTextBox
上显示错误模板?
答案 0 :(得分:0)
据我所知,您的问题是IDataErrorInfo
需要在您要绑定的类上实现,在您的ControlTemplate
中,您要绑定到您的Text
-Property WrappedTextBox
,因此您的WrappedTextBox
本身必须实现IDataErrorInfo
才能对您的TextBox
进行验证。
也请阅读此article,而不是创建新控件也可以做。
对于您要实现的目标,我想到了两个选择(注意:该选择是在您做更多事情的前提下创建的,因此前面提到的文章的选择不适用于您)
选项1 :直接从TextBox
后面的代码:
class WrappedTextBox : TextBox
{
}
样式:
<Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<AdornerDecorator>
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
</AdornerDecorator>
<-- ControlTemplate.Triggers etc. -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用法:(与以前相同)
<local:WrappedTextBox
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />
选项2 :通过Binding
本身
后面的代码:
[TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
class WrappedTextBox : Control
{
private TextBox _partTextBox;
private BindingBase _textBinding;
public BindingBase TextBinding
{
get => _textBinding;
set
{
if (_textBinding != value)
{
_textBinding = value;
ApplyTextBinding();
}
}
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
ApplyTextBinding();
}
private void ApplyTextBinding()
{
if (_partTextBox != null)
BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
}
}
样式:
<Style TargetType="local:WrappedTextBox">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:WrappedTextBox">
<Grid>
<AdornerDecorator>
<TextBox x:Name="PART_TEXTBOX" />
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用法:
<local:WrappedTextBox
TextBinding="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />