我有一个带有GroupBox的表单,其中有很多控件(Checkbox,TextBox和Combobox)。
表单绑定到在其属性上实现IDataErrorInfo的视图模型,当用户向控件输入无效值时,IDataInfo返回无效结果,并且控件被常用的红色框包围,并且错误消息显示在表单的底部。
问题是,GroupBox旨在表示一组强制值。用户需要检查组中的至少一个复选框。如果不这样做不是单个控件的错误,那就是组中的错误。所以我在GroupBox中添加了一个BindingGroup,并添加了ValidationRule,如果没有选择任何内容则返回错误。这很好。如果未选择任何内容,则GroupBox将被常用的红色框包围,并且错误消息将显示在表单的底部。
我的问题是,如果GroupBox中的一个控件未通过验证,我会得到两个红色框 - 一个围绕控件,一个围绕GroupBox。我在表单底部的列表中收到两条错误消息。
如何防止BindingGroup报告组中包含的所有内容的错误?
编辑:
一个简单的例子 - 这不会显示Validation.Errors,但是当包含的TextBox出现时,您可以看到StackPanel突出显示为验证失败。
XAML:
<Window
x:Class="BugHunt5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BugHunt5"
Title="MainWindow"
Height="350"
Width="525"
>
<GroupBox
Margin="20"
Header="This is my group"
x:Name="MyGroupBox"
>
<StackPanel>
<StackPanel.BindingGroup>
<BindingGroup NotifyOnValidationError="True">
</BindingGroup>
</StackPanel.BindingGroup>
<TextBox
Height="30"
Width="100"
>
<TextBox.Text>
<Binding
NotifyOnValidationError="True"
ValidatesOnDataErrors="True"
Path="MyString"
UpdateSourceTrigger="PropertyChanged"
>
<Binding.ValidationRules>
<local:NoDecimalsValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
</GroupBox>
</Window>
C#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel("This should be an integer");
}
}
public class ViewModel
{
public string MyString
{ get; set; }
public ViewModel(string mystring)
{ this.MyString = mystring; }
}
public class NoDecimalsValidationRule : ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
string myString = value as string;
int result;
if (!Int32.TryParse(myString, out result))
return new ValidationResult(false, "Must enter integer");
return new ValidationResult(true, null);
}
}
答案 0 :(得分:1)
<强> ViewModel.cs 强>
public class ViewModel : INotifyPropertyChanged, IDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
private bool checked1, checked2;
private string myString;
public bool Checked1
{
get { return this.checked1; }
set { this.SetValue(ref this.checked1, value, "Checked1"); }
}
public bool Checked2
{
get { return this.checked2; }
set { this.SetValue(ref this.checked2, value, "Checked2"); }
}
public string MyString
{
get { return this.myString; }
set { this.SetValue(ref this.myString, value, "MyString"); }
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler != null)
handler(this, e);
}
private void SetValue<T>(ref T field, T value, string propertyName)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
}
public string Error
{
get
{
return this.checked1 == false && this.checked2 == false ? "Must check one value." : string.Empty;
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
switch (propertyName)
{
case "MyString":
int result;
return int.TryParse(this.myString, out result) ? string.Empty : "Must enter integer.";
default:
return string.Empty;
}
}
}
}
<强> MainWindow.xaml 强>
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication"
Title="MainWindow" Height="350" Width="525">
<GroupBox Header="This is my group">
<GroupBox.DataContext>
<local:ViewModel MyString="This should be an integer"/>
</GroupBox.DataContext>
<StackPanel>
<StackPanel.BindingGroup>
<BindingGroup x:Name="checkedBindingGroup">
<BindingGroup.ValidationRules>
<DataErrorValidationRule ValidationStep="ConvertedProposedValue"/>
</BindingGroup.ValidationRules>
</BindingGroup>
</StackPanel.BindingGroup>
<CheckBox IsChecked="{Binding Checked1, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Binding.SourceUpdated="OnCheckedSourceUpdated" Content="Checked1"/>
<CheckBox IsChecked="{Binding Checked2, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Binding.SourceUpdated="OnCheckedSourceUpdated" Content="Checked2"/>
<TextBox Text="{Binding MyString, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, BindingGroupName=Dummy}"/>
</StackPanel>
</GroupBox>
</Window>
<强> MainWindow.xaml.cs 强>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnCheckedSourceUpdated(object sender, DataTransferEventArgs e)
{
this.checkedBindingGroup.ValidateWithoutUpdate();
}
}
关键词:
答案 1 :(得分:0)
我曾经遇到过类似的问题,但似乎没有合乎逻辑的方法(因为它会导致像矛盾一样)。
但是,您可以做的是使用与该组相关联的复选框或面板的附加属性Validation.ErrorTemplate
进行修补,以删除红色轮廓。