我错过了什么?
1-风格
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Validation.HasError}" Value="true">
<Setter Property="BorderBrush" Value="Blue" />
</DataTrigger>
</Style.Triggers>
<Setter Property="MinWidth" Value="160" />
<Setter Property="Margin" Value="0 7 0 0"/>
</Style>
Run Code Online (Sandbox Code Playgroud)
2 - Viewmodel在视图中实现IDataErrorInfo 3- textBox
<TextBox x:Name="FirstName" Text="{Binding Person.FirstName, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true}"></TextBox>
Run Code Online (Sandbox Code Playgroud)
3 - 我使用Caliburn MVVM
我"BindingExpression路径错误:对 '对象' '' PersonWindowViewModel未找到 '验证' 属性 '(的HashCode = 38783181)' BindingExpression:路径= Validation.HasError;的DataItem = 'PersonWindowViewModel'(的HashCode = 38783181);目标元件是'TextBox'(Name ='FirstName'); target属性为'NoTarget'(类型'Object')"S
使用MVVM.我有一个DataTemplate用于显示扩展器的扩展器,每个对象都有一些控件.
<DataTemplate>
<Expander ExpandDirection="Down" IsExpanded="False">
<Expander.Header>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="Platform Group {0} {1}">
<Binding Path="PlatformGroupCode"/>
<Binding Path="PlatformGroupName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Expander.Header>
<vw:PlatformGroup HorizontalAlignment="Left"/>
</Expander>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
在该视图内部是绑定到这2个属性的2个文本框.我IDataErrorInfo在我的VM中使用进行验证,我在主应用程序资源中使用了一种样式,将错误消息显示为工具提示:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Run Code Online (Sandbox Code Playgroud)
添加新组时,2个属性具有默认值,这是无效的,因此我希望文本框为红色以提示用户输入数据.如果Expander的IsExpanded设置为true,则此方法有效.但如果它是假的,我必须扩展并更改其中一个文本框中的值,以便显示红色边框和工具提示.
我不想将扩展器设置为扩展,因为最终会有很多控件.扩展器扩展后如何才能显示红色边框?更好的是,是否有办法使新添加的扩展器扩展(当用户添加新组时,我将PlatformGroupviewModel添加到observablecollectionPlatformGroupviewModel中)?
编辑更多细节:顶级视图:
<StackPanel Orientation="Vertical">
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="630">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.ColumnSpan="2" Grid.Row="1" HorizontalAlignment="Stretch"> …Run Code Online (Sandbox Code Playgroud) 我在我的ViewModel中实现了IDataErrorInfo,如果文本框有错误,则返回一个字符串.
public string this[string columnName]
{
get { return "Error-- This is a long error message - sd"; }
}
Run Code Online (Sandbox Code Playgroud)
但是此错误消息会在UI上的其他控件后面显示,如下所示.

下面是xaml:
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Window.Resources>
<ControlTemplate x:Key="validationTemplateNew">
<DockPanel LastChildFill="True">
<TextBlock Name="ErrorText" DockPanel.Dock="Bottom" Foreground="White" Background="Red"
FontSize="12" Padding="2" FontFamily="Trebuchet MS"
Margin="5,5,0,0"
TextWrapping="Wrap"
Text="{Binding [0].ErrorContent}" ></TextBlock>
<AdornedElementPlaceholder Name="ErrorTextBox" />
</DockPanel>
</ControlTemplate>
<Style x:Key="ValidationStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BitmapEffect">
<Setter.Value>
<BitmapEffectGroup>
<OuterGlowBitmapEffect GlowColor="Red" GlowSize="3" Noise="0.6"></OuterGlowBitmapEffect>
</BitmapEffectGroup>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources> …Run Code Online (Sandbox Code Playgroud) 我遇到了多个字段之间的验证问题.例如 - 我得到了一个名为RangeDateViewModel的ViewModel,它包含名为DateViewModel的类的2个实例,每个实例分别代表一个开始日期和结束日期.
所以我的绑定看起来像这样 -
<TextBox Text="{Binding StartDate.Date, ValidateOnDataError=True}">
<TextBox Text="{Binding EndDate.Date, ValidateOnDataError=True}">
Run Code Online (Sandbox Code Playgroud)
我的RangeDateViewModel类实现了IDataErrorInfo接口.在我的计划中,RangeDateViewModel将通过在IDataErrorInfo ["propertyName"]函数中应用验证逻辑来验证开始日期是否在结束日期之前 -
public string this[string columnName]
{
get
{
return ValidationError();
}
}
Run Code Online (Sandbox Code Playgroud)
问题是永远不会调用它,而是调用驻留在每个DateViewModel类中的IDataErrorInfo属性.
我想这是因为bound属性不在RangeDateViewModel的同一级别,而是在子DateViewModel中.
我认为我的需求是非常基本的,必须有一个简单的解决方案来解决这个问题.我尝试使用ValidationRules而不是IDataErrorInfo,但后来我遇到了问题,让ViewModel知道ValidationRules当前的验证状态.
我有一个用于显示红色边框和控件周围错误消息的模板。它可以工作(在TextBoxes和ComboBoxes上测试)。但是在两个特定的组合框上却没有。
好吧,让我们看看VM的不同之处:
简而言之,VM没什么区别。
视图是完全相同的,使用了相同的样式,因此总之两者之间也没有区别。
因此,我添加NotifyOnValidationError=True到了ValidatesOnDataErrors=True已经存在的位置,并订阅了Validation.Error... 并且它被触发了!但是模板仍然没有显示。我没有主意,请建议我检查一下!
编辑:进一步的研究:
我已经反编译了DataErrorValidationRule,并将其重新编译为MyDataErrorValidationRule,以使其与原始数据尽可能接近。我删除了ValidatesOnDataErrors=True,并添加了ValidationRule进行调试。它返回new ValidationResult(false, (object)str);了两次包含正确错误消息的str-一次用于将属性设置为null,一次用于强制验证整个对象。模板仍未显示。
我还检查了控件上的Validation.GetErrorTemplate(在第一次触发Validation.Error时),它不是NOT NULL,因此也不DynamicResource是失败的原因。
编辑:工作示例:
<ItemsControl ItemsSource="{Binding QuestionAnswers}">
<ItemsControl.Resources>
<!-- ... -->
<DataTemplate DataType="{x:Type Model:QuestionAnswerModel}">
<StackPanel>
<!-- here is the combo box -->
<ComboBox Margin="8,4" Padding="8" MinWidth="120" HorizontalAlignment="Left"
Validation.ErrorTemplate="{DynamicResource DefaultValidationErrorTemplate}"
ItemsSource="{Binding Options.Source}"
DisplayMemberPath="ItemName" SelectedValuePath="ItemID"
SelectedValue="{Binding Options.SelectedID, ValidatesOnDataErrors=true}" />
</StackPanel>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
非工作示例:
<ComboBox Margin="8,4" Padding="8" MinWidth="120" HorizontalAlignment="Left" …Run Code Online (Sandbox Code Playgroud) 我有一个ViewModel类,Phone对象作为其属性之一,我的主窗口数据上下文设置为ViewModel,我是否需要在底层Phone模型类或包含Phone属性的ViewModel类上实现IDataErrorInfo?
另外,将我正在尝试验证的文本框绑定到我的ViewModel.NewPhone.StringProperty的正确方法是什么?
非常感谢
我有一个用户控件来验证它的内容。
我正在使用 IDataErrorInfo 来验证输入(我必须使用 .Net 3.5)。
我正在关注本教程:http : //japikse.blogspot.ch/2009/07/idataerrorinfo-error-templates-and-wpf.html
这意味着我正在使用以下样式:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Background" Value="Pink"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True"
ToolTip="{Binding ElementName=controlWithError,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock DockPanel.Dock="Right"
Foreground="Red"
FontSize="14pt"
Margin="-15,0,0,0" FontWeight="Bold">*
</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="controlWithError" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
Run Code Online (Sandbox Code Playgroud)
问题是,在某些情况下,我必须隐藏表单(当没有选择任何元素时),但是当我显示的表单没有错误时,然后我折叠表单(网格),UserControls 中的文本框(这是无效的,因为它们不接受空值)得到红色边框和星号:

未隐藏时的相同形式:
请注意:只有 ErrorTemplate 的内容是可见的,触发器的内容(粉红色背景,黑色前景)不适用。
所以我认为这种风格有问题,但我对 WPF 风格不够熟悉,不知道为什么。
另一个奇怪的事情:如果我有具有相同验证的文本框(而不是用户控件中的文本框),它们会被正确隐藏。
编辑 我发现了一些对我有很大帮助的其他东西,首先,这个主题: 隐藏控件时隐藏验证装饰 有了这个,我做了以下事情:将我的用户控件可见性绑定到隐藏元素可见性,然后在用户控件中,我将文本框可见性绑定到用户控件可见性,然后(最后),我添加一个样式触发器:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Background" Value="Pink"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger> …Run Code Online (Sandbox Code Playgroud) 我总是实现IDataErrorInfo接口,而实际上并不知道这条线的含义及其工作原理.
string IDataErrorInfo.this[string propertyName]
{
get { return this.GetValidationError(propertyName); }
}
Run Code Online (Sandbox Code Playgroud)
如何.this[string propertyName]工作,以及何时/如何调用此属性?
对于我的 WPF 应用程序,我决定使用 MVVM。这是我将如何实现这种模式的概念。
我的第一个问题是关于在 ViewModel 中包装或不包装我的模型。
ViewModel 出于各种原因应该包装模型:
我不喜欢直接绑定到 Model (DateTime, int, ...) 中的强类型属性,因为当我这样做时 => WPF 会控制我对这些类型的验证。这真的很糟糕,因为当用户在 Datepicker 中写入 'aaaa' 时,我的模型是有效的(我的模型从不知道这一点,因为 WPF 控制强类型属性)并且启用了保存按钮 - 这真的是错误的。
我没有向视图公开我的模型的所有属性,我ViewModel应该保护我的模型(我有一些属性,应该在表示层只有 getter 而没有 setter)
我的决定是ViewModel绝对应该包装模型。所以ViewModel工具INotifyPropertyChanged。
但是现在我在业务验证方面遇到了问题。
当我使用漂亮的 IDataErrorInfo 时,我在 ViewModel 中拥有整个业务规则,这打破了我的概念。业务规则绝对应该在模型中。
示例:当用户选择类型 A 时,则字段 1 和字段 2 为必填项。当用户选择类型 B 时,字段 3 是必填项——该字段应标记为红色,并且在无效时禁用保存按钮。还有更重的东西,比如空闲/占用的 DateTime-Ranges。
当我在 ViewModel 中做这些事情时,这绝对是糟糕的,因为大多数事情都是业务部分。
那么我如何才能做到这一点?
目前我有这个解决方法:
所有ValidationRules都在模型中作为简单的方法,例如
public string ValidateBirthday(string birthay)
{
if …Run Code Online (Sandbox Code Playgroud) public string this[string columnName]实现IDataErrorInfo接口时有什么意义?
public string this[string columnName]
{
get
{
switch (columnName)
{
case "Name":
return ValidateName();
case "PhoneNumber":
return ValidatePhoneNumber();
default:
return string.Empty;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么有方括号及其功能.
答: 感谢Hans和Scott现在我知道这只是索引器的语法.更多信息在这里.
idataerrorinfo ×10
wpf ×10
mvvm ×6
validation ×5
c# ×3
caliburn ×1
expander ×1
indexer ×1
styles ×1