我正在尝试在同时使用Textboxes和DataGrid的WPF应用程序中验证Textbox。
验证在加载时触发-显示文本框为空。但是,当我实际上在文本框中输入内容然后移到另一个时,它仍然显示为无效-验证不会再次触发。
数据网格和文本框都使用数据绑定,以便从数据库加载和写入数据。
我根据本教程https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-binding-validation创建了一个验证规则。
大多数情况下,此解决方案对我有用-当我首先在datagrid中选择一行,然后开始更改文本框的内容时-验证有效。 但是,如前所述-当应用启动且未选择任何内容(且文本框为空)时,它无法正常工作。
XAML 文件的以下片段:
<Window.Resources>
<CollectionViewSource x:Key="printLogViewSource" d:DesignSource="{d:DesignInstance {x:Type local:PrintLog}, CreateList=True}" >
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Name"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
</Window.Resources>
<Grid Background="#FFE5E5E5" Width="Auto" DataContext="{StaticResource printLogViewSource}">
<GroupBox x:Name="groupBox" Header="Add/Update/Remove" Margin="10,573,10,15">
<Grid Margin="0,0,0,0">
<Grid x:Name="grid1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Name:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
<TextBox x:Name="nameTextBox" Validation.ErrorTemplate="{StaticResource validationTemplate}" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" VerticalAlignment="Center" Width="120" AutomationProperties.IsRequiredForForm="True">
<TextBox.Text>
<Binding Path="Name"
Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:ValRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</Grid>
<Grid x:Name="grid2" HorizontalAlignment="Left" Margin="191,10,0,0" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Person:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
<TextBox x:Name="personTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding Person, Mode=OneWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=Explicit}" VerticalAlignment="Center" Width="120"/>
</Grid>
</Grid>
</GroupBox>
<DataGrid x:Name="printLogDataGrid" AutoGenerateColumns="False" IsReadOnly="True" EnableRowVirtualization="True" ItemsSource="{Binding Source={StaticResource printLogViewSource}, UpdateSourceTrigger=PropertyChanged}" Margin="10,10,10,141" RowDetailsVisibilityMode="VisibleWhenSelected" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="printIDColumn" Binding="{Binding PrintID}" Header="Print ID" Width="Auto" IsReadOnly="True"/>
<DataGridTextColumn x:Name="nameColumn" Binding="{Binding Name}" Header="Name" Width="Auto"/>
<DataGridTextColumn x:Name="personColumn" Binding="{Binding Person}" Header="Person" Width="Auto"/>
</DataGrid.Columns>
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<DataGridCell Content="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
</Grid>
这是我的 ValidationRule :
class ValRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if ((string)value == "")
{
return new ValidationResult(false, "Field cannot be empty");
}
else
{
return ValidationResult.ValidResult;
}
}
}
这是我的 MainWindow.xaml.cs 的片段:
public partial class MainWindow : Window
{
private printDBEntities _context = new printDBEntities();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_context.PrintLogs.Load();
System.Windows.Data.CollectionViewSource printLogViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("printLogViewSource")));
printLogViewSource.Source = _context.PrintLogs.Local;
printLogDataGrid.SelectedIndex = -1;
//I'm setting this value to -1 so that on load my TextBoxes are empty.
//If i don't add this, on load my textboxes have value corrseponding to first row of datagrid.
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
this._context.Dispose();
}
//Below normally are functions responsible for Add/Update/Remove buttons
}
在加载窗口时,行printLogDataGrid.SelectedIndex = -1;
是否部分负责此问题?
如代码中所提到的-如果我跳过此步骤,则在开始时选择datagrid的第一行,这意味着文本框也将在开始时填充数据-这意味着用户必须从每个框中删除文本才能添加新的记录。
编辑
为弄清这种情况-不能正常工作的文本框是nameTextBox-目前唯一经过验证的文本框。
答案 0 :(得分:0)
<TextBox x:Name="nameTextBox" Validation.ErrorTemplate="{StaticResource validationTemplate}" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" VerticalAlignment="Center" Width="120" AutomationProperties.IsRequiredForForm="True">
<TextBox.Text>
<Binding Path="Name"
Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="True"
ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<local:ValRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
NotifyOnValidationError和ValidatesOnNotifyDataErrors应该这样做。