我有以下XAML代码,表示带有验证的TextBox,当发生错误时,边距增加,因此消息不会与此TextBox下的其他UI元素重叠。
在XAML中,每个部分的工作方式都与我打算的一样。
验证是通过IDataErrorInfo
接口
<TextBox
Grid.Column="1"
Validation.ErrorTemplate="{StaticResource validationErrorTemplate}"
Style="{StaticResource baseMargins}"
Margin="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.HasError), Converter={StaticResource MarginConv}}"
Padding="{StaticResource basePadding}">
<TextBox.Text>
<Binding
Path="Email"
Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnDataErrors="True"/>
</TextBox.Text>
</TextBox>
现在,我希望在运行时创建相同的内容。页面上有一个ItemsControl
,我用生成的TextBoxes
填充。
以下代码显示了我如何创建此TextBox
private static void CreateForStackOverflow()
{
TextBox textBox = new TextBox();
Binding textBinding = new Binding();
textBinding.Path = new PropertyPath("Email");
textBinding.Mode = BindingMode.TwoWay;
textBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
textBinding.ValidatesOnDataErrors = true;
textBinding.NotifyOnValidationError = true;
textBox.SetBinding(TextBox.TextProperty, textBinding);
var valTemplate = (ControlTemplate)Application.Current.FindResource("validationErrorTemplate");
Validation.SetErrorTemplate(textBox, valTemplate);
Binding valBinding = new Binding();
valBinding.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
valBinding.Path = new PropertyPath("Validation.HasError");
valBinding.Converter = new Converters.BoolMarginConverter();
textBox.SetBinding(FrameworkElement.MarginProperty, valBinding);
}
现在验证有效,将创建错误,但是唯一不起作用的是MarginProperty
的绑定。这是永远不会触发的。
“输出”窗口中显示以下错误:
BindingExpression path error: 'Validation' property not found on 'object' ''TextBox' (Name='')'. BindingExpression:Path=Validation.HasError;
DataItem='TextBox' (Name='');
target element is 'TextBox' (Name='');
target property is 'Margin' (type 'Thickness')
我发现它可能与我的`DataContext]有关,但是它是在XAML中设置的,并且设置Context是所有这些人的解决方案,而不是我的解决方案。
使用窥探(2.10.0.0),我可以看到TextBox
具有Validation
属性。
BoolMarginConverter的代码如下:
public class BoolMarginConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
bool hasError = (bool)value;
return hasError ? new Thickness(2, 2, 2, 20) : new Thickness(2, 2, 2, 2);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
但这从未执行过,因为找不到Validation.HasError
。
我在这里想念什么?
谢谢。
编辑:错误模板
<ControlTemplate x:Key="validationErrorTemplate">
<DockPanel>
<StackPanel
Orientation="Horizontal" DockPanel.
Dock="Bottom"
ClipToBounds="True">
<Grid
Width="12"
Height="12">
<Ellipse
Width="12"
Height="12"
Fill="Red"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBlock
Foreground="White"
FontWeight="Heavy"
FontSize="8"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
Text="X"
ToolTip="{Binding ElementName=ErrorAdorner, UpdateSourceTrigger=PropertyChanged,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
</Grid>
<TextBlock
Foreground="Red"
FontWeight="Bold"
TextWrapping="NoWrap"
TextTrimming="WordEllipsis"
Margin="2,0,0,0"
Text="{Binding ElementName=ErrorAdorner, Path=AdornedElement.(Validation.Errors), Converter=converters:ValidationErrorsToStringConverter}}"
/>
</StackPanel>
<AdornedElementPlaceholder x:Name="ErrorAdorner"/>
</DockPanel>
</ControlTemplate>
答案 0 :(得分:1)
我错过了(Validation.HasError)
上的括号...
Validation.HasError
==> (Validation.HasError)
valBinding.Path = new PropertyPath("(Validation.HasError)");
也许有一天这会帮助某人。
谢谢
答案 1 :(得分:0)
我不会使用代码来完成所有这些工作,即使那样,您似乎还有些复杂。 以下标记对我有效。 我在代码的后面有一个公共Int属性,只需输入一个字符即可进行测试。
很显然,如果您想通过代码应用此样式,请在样式上放置一个x:Key,然后可以获取它的资源并应用它。我的适用于所有文本框。我真的不明白为什么你不希望那样。
我还建议像这样移动ui是有限制的。我希望边框和轮廓的颜色发生变化,并在工具提示中查看所有错误。您只能以这种方式适合一个人。
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<StackPanel
Orientation="Horizontal" DockPanel.Dock="Bottom"
ClipToBounds="True">
<Grid
Width="12"
Height="12">
<Ellipse
Width="12"
Height="12"
Fill="Red"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBlock
Foreground="White"
FontWeight="Heavy"
FontSize="8"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
Text="X"
ToolTip="{Binding ElementName=ErrorAdorner, UpdateSourceTrigger=PropertyChanged,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
</Grid>
<TextBlock
Foreground="Red"
FontWeight="Bold"
TextWrapping="NoWrap"
TextTrimming="WordEllipsis"
Margin="2,0,0,0"
Text="{Binding ElementName=ErrorAdorner, Path=AdornedElement.(Validation.Errors)/ErrorContent}"
/>
</StackPanel>
<AdornedElementPlaceholder x:Name="ErrorAdorner"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)/ErrorContent}"/>
<Setter Property="Margin" Value="0,0,0,20"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<TextBox Text="{Binding MyNum, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="Banana"/>
<Button Content="Some Button"/>
</StackPanel>
</Grid>