我希望这个问题没有在其他地方被问到,但是我很难找到正确的搜索词来找到这个问题的任何已经存在的答案。
我正在用 C# WPF (MVVM) 实现一个程序,其中有许多采访风格的屏幕,用户可以在其中有序地输入科学数据。我们希望Textbox
' 和DataGrid
' 根据该控件中的数据是由用户输入、由程序输入为默认值还是来自用户导入的另一个文件。最重要的是,我们希望 UI 响应来自 ViewModel 中实现的 IDataErrorInfo 的验证检查。
因此,如果 TextBox 中显示的数据是模板值,则它可能是蓝色的;如果是程序默认值,则显示为绿色;如果用户输入,则显示为黑色;如果 IDataErrorInfo 表明它是错误数据,则显示为红色。
我实现这一点的最初答案是创建一个自定义类:
class AdornerString{
private string _myString;
private bool _isTemplate;
private bool _isDefault;
public string MyString{
get{
etc.
}
set{
etc.
}
}
// accessor properties and Constructors omitted for brevity
}
然后我TextBox.Text
在 View 中拥有我的所有属性,如下所示:
<TextBox Text="{Binding Path=someAdornerString.MyString,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"/>
并使用响应 someAdornerString 的属性的 DataTriggers 应用样式以创建适当的颜色。
但是,ViewModel 上的 IDataErrorInfo 不再验证 TextBox。为什么会这样,有没有更好的方法来解决我的问题?我无法在 AdornerString 类中进行验证。
一种可能的解决方法,尽管不可取:
我能想到的唯一其他解决方案是在 ViewModel 中为用户输入的每个字段设置两个属性——一个用于数据本身,另一个是与上面相同的自定义类减去字符串。但是,这意味着我无法概括用于文本框的样式。每个 TextBox 都必须有一个像这样的自定义样式:
<TextBox.Style>
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource OtherStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=**instanceCustomClass**.IsDefault}"
Value="True">
<Setter Property="Foreground"
Value="Green" />
</DataTrigger>
<Trigger Property="Validation.HasError"
Value="true">
<Setter Property="Foreground"
Value="OrangeRed" />
</Trigger>
</Style.Triggers>
</Style>
因为每个 UI 字段都有一个与之关联的特定自定义类。
我宁愿不以这种方式实现,因为我可能有 100 多页输入屏幕,每个屏幕都有 1-12TextBox
个,忽略混合中抛出的 DataGrids(具有并行数据数组及其关联的自定义类) .
有任何想法吗?我已经阅读了自定义验证,但我还没有看到这在这种情况下会有什么帮助。