我正在尝试验证UserControl元素中的一个表单,该表单正由Window内的另一个UserControl使用。 我正在使用MVVM模式,并且我在最后一个UserControl子节点的ViewModel中实现了INotifyDataErrorInfo。 问题是,当发生错误时,UserControl中的TextBox绑定到生成错误的属性,而UserControl本身被一个指示错误的红色框包围,我想只需要TextBox突出显示。
以下是代码:
具有MainView(或第一个UserControl)的窗口:
<Grid>
<pages:MainPage>
<pages:MainPage.DataContext>
<vm:MainViewModel/>
</pages:MainPage.DataContext>
</pages:MainPage>
</Grid>
(它只包含一个UserControl作为页面)
&#34; MainPage&#34;的UserControl,其中包含另一个(和最后一个)UserControl作为页面内的页面:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:SearchViewModel}">
<pages:SearchPage/>
</DataTemplate>
...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
...
<ContentControl Content="{Binding CurrentPage}"/>
好的,现在相信我,&#34; CurrentPage&#34;有一个取自MainViewModel属性的ViewModel对象,所以我们假设&#34; CurrentPage&#34;是一个&#34; SearchViewModel&#34;对象,所以我们有SearchPage UserControl。
现在是最后一个UserControl,SearchPage:
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding CaseNumber}"/>
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding PatientNumber}"/>
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding PatientName}"/>
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding PatientFamilyName}"/>
<TextBox Grid.Column="1" Grid.Row="4" Text="{Binding PatientMotherMaidenName}"/>
<TextBox Grid.Column="1" Grid.Row="5" Text="{Binding DoctorName}"/>
为了让帖子尽可能小,我刚刚添加了#34;表格&#34; UserControl的一部分。
现在最重要的部分是带有INotifyDataErrorInfo实现的SearchViewModel:
public class SearchViewModel : ViewModelBase, INotifyDataErrorInfo, IVMPage
{
private SearchModel searchModel = new SearchModel();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();
private string patientNumber;
public string PatientNumber
{
get { return patientNumber; }
set
{
int number;
patientNumber = value;
if (int.TryParse(value, out number))
{
searchModel.PatientNumber = number;
ClearErrors("PatientNumber");
}
else
{
AddErrors("PatientNumber", new List<string> { "The value must be a number" });
}
RaisePropertyChanged("PatientNumber");
}
}
private string caseNumber;
public string CaseNumber
{
get { return caseNumber; }
set
{
int number;
caseNumber = value;
if (int.TryParse(value, out number))
{
searchModel.CaseNumber = number;
ClearErrors("CaseNumber");
}
else
{
AddErrors("CaseNumber", new List<string> { "The value must be a number" });
}
RaisePropertyChanged("CaseNumber");
}
}
....
private void ClearErrors(string propertyName)
{
errors.Remove(propertyName);
if (ErrorsChanged != null)
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
private void AddErrors(string propertyName, List<string> newErrors)
{
errors.Remove(propertyName);
errors.Add(propertyName, newErrors);
if(ErrorsChanged != null)
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
public System.Collections.IEnumerable GetErrors(string propertyName)
{
if(string.IsNullOrEmpty(propertyName))
{
return errors.Values;
}
else
{
if(errors.ContainsKey(propertyName))
{
return errors[propertyName];
}
else
{
return null;
}
}
}
public bool HasErrors
{
get { return (errors.Count() > 0); }
}
所以,问题是: 例如,如果我在&#34; CaseNumber&#34;中引入字符。 TextBox,它被一条红线包围,表示错误,所有的SearchPage UserControl也被另一条红线包围。我想要的只是用红线标记TextBox以指示错误而不是所有UserControl。
奇怪的是,如果我在AddError和ClearError方法中注释了ErrorChanged事件被触发的部分,那么UserControl不再被红线包围......但我不知道为什么..
很抱歉这个问题很长,谢谢。
答案 0 :(得分:0)
好的,答案很简单。 问题在于这一行:
<ContentControl Content="{Binding CurrentPage}"/>
因为默认情况下WPF将ValidatesOnNotifyDataErrors属性设置为true,所以当“CurrentPage”UserControl内部发生错误时,在UserControl中生成错误的TextBox会按预期指示错误,并在其周围显示红线,但也是ContentControl检查“GetErrors”方法并在所有“CurrentPage”UserControl中绘制另一条红线。
要避免这种情况,只是在TextBox而不是所有UserControl中指出错误,只需将其添加到ContentControl声明:
<ContentControl Content="{Binding CurrentPage, ValidatesOnNotifyDataErrors=False}"/>
答案 1 :(得分:-1)
为文本框的背景而不是边框着色。
去过那里,碰到那个问题。文本框的边界很难改变,因为很多东西都在玩它。例如,如果您使用的是DevExpress,则必须覆盖整个文本框样式以获取边框,然后在选中该框时开始失去自然突出显示等。
因此,我建议将文本框的背景着色以指示错误。它对用户来说更加明显,看起来很棒,并且在实践中运作良好。
使用浅红色,此页面适合查找与页面现有颜色方案一致的颜色: