我正在使用 System.Windows.Controls.DataGrid(WPF、.NET 4.0、C#)。如果单元格的验证失败 (HasErrors == TRUE),确定按钮应该是灰色的 (IsEnabled = FALSE)。
使用 ValidationRule 执行 DataGrid 验证。
我在 StackOverflow 上阅读了几篇密切相关的文章,但我仍然卡住了。我认为问题在于 Validation 在 DataGridRow 上,但 OK 按钮的 IsEnabled 绑定正在查看整个网格。
要查看错误,请在网格中添加第三行,并输入无效数字(例如 200)。或者只需将两个股票值之一编辑为无效(小于 0、非整数或大于 100 )。
这是xaml:
<Window x:Class="SimpleDataGridValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:SimpleDataGridValidation"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<c:BoolToOppositeBoolConverter x:Key="boolToOppositeBoolConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<DataGrid Name="myDataGrid"
ItemsSource="{Binding}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Time"
x:Name="TimeField">
<DataGridTextColumn.Binding>
<Binding Path="Time"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<c:TimeValidationRule />
</Binding.ValidationRules>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
<DataGrid.RowValidationErrorTemplate>
<ControlTemplate>
<Grid Margin="0,-2,0,-2"
ToolTip="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridRow}},
Path=(Validation.Errors)[0].ErrorContent}">
<Ellipse StrokeThickness="0"
Fill="Red"
Width="{TemplateBinding FontSize}"
Height="{TemplateBinding FontSize}" />
<TextBlock Text="!"
FontSize="{TemplateBinding FontSize}"
FontWeight="Bold"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</DataGrid.RowValidationErrorTemplate>
</DataGrid>
<Button Name="btnOk"
Width="40"
Content="_OK"
IsDefault="True"
Grid.Row="1"
Click="btnOk_Click"
IsEnabled="{Binding ElementName=myDataGrid, Path=(Validation.HasError), Converter={StaticResource boolToOppositeBoolConverter}}">
</Button>
</Grid>
</Window>
这是 C# 代码隐藏:
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace SimpleDataGridValidation
{
public partial class MainWindow : Window
{
public ObservableCollection<CTransition> Transitions;
public MainWindow()
{
InitializeComponent();
Transitions = new ObservableCollection<CTransition>();
Transitions.Add(new CTransition(10, 5));
Transitions.Add(new CTransition(20, 7));
myDataGrid.DataContext = Transitions;
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
public class CTransition
{
public int Time { get; set; }
public int Speed { get; set; }
public CTransition()
{ }
public CTransition(int thetime, int thespeed)
{
Time = thetime;
Speed = thespeed;
}
}
public class TimeValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (value != null)
{
int proposedValue;
if (!int.TryParse(value.ToString(), out proposedValue))
{
return new ValidationResult(false, "'" + value.ToString() + "' is not a whole number.");
}
if (proposedValue > 100)
{
return new ValidationResult(false, "Maximum time is 100 seconds.");
}
if (proposedValue < 0)
{
return new ValidationResult(false, "Time must be a positive integer.");
}
}
// Everything OK.
return new ValidationResult(true, null);
}
}
[ValueConversion(typeof(Boolean), typeof(Boolean))]
public class BoolToOppositeBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool) && targetType != typeof(System.Nullable<bool>))
{
throw new InvalidOperationException("The target must be a boolean");
}
if (null == value)
{
return null;
}
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool) && targetType != typeof(System.Nullable<bool>))
{
throw new InvalidOperationException("The target must be a boolean");
}
if (null == value)
{
return null;
}
return !(bool)value;
}
}
}