我正在创建一个DataTable
,其列存储在列表中。
public class CustomColumn
{
public string ColumnName { get; set; }
public int MinLength { get; set; }
public int MaxLength { get; set; }
}
public class ViewModel
{
public List<CustomColumn> Columns { get; set; }
public DataTable MyTable { get; set; }
public ViewModel()
{
InitializeCustomColumns();
MyTable = new DataTable();
foreach (CustomColumn column in Columns)
{
MyTable.Columns.Add(column.ColumnName, typeof(string));
}
}
}
现在我将DataTable
绑定到DataGrid
并允许用户在DataGrid
中添加行。在运行时初始化列列表时,将自动生成我的DataGrid
列。当用户在行的特定列中输入某个值时,我想基于CustomColumn
属性 - &gt;进行验证。 MinLength
(最小字符串长度)&amp; MaxLength
(允许的最大字符串长度)。如果验证失败,我想显示DataGrid中出现的默认红色边框,表示无效输入。我正在关注MVVM软件架构模式。
修改
我附上ColumnChanging
听众
MyTable.ColumnChanging += tableColumnChanging;
private void tableColumnChanging(object sender, DataColumnChangeEventArgs e)
{
//I am able to validate here using my logic
if(!isValid(e))
{
object badValue = e.ProposedValue;
e.ProposedValue = "Bad Data";
e.Row.RowError = "The column contains an error";
e.Row.SetColumnError(e.Column, "Column cannot be " + badValue);
}
else
{
...
}
}
我能够验证,但我想显示我的单元格!标记如果isValid
返回false。
答案 0 :(得分:1)
我设法为同一个
做了一个解决方法XAML
<ScrollViewer xmlns:l="clr-namespace:CSharpWPF">
<ScrollViewer.Resources>
<DataTemplate DataType="{x:Type l:CustomTable}">
<DataTemplate.Resources>
<l:ErrorToVisibilityConverter x:Key="ErrorToVisibilityConverter" />
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Grid Background="{TemplateBinding Background}">
<StackPanel Orientation="Horizontal">
<TextBlock Text=" ! "
FontWeight="Bold"
Foreground="Red">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource ErrorToVisibilityConverter}"
Mode="OneWay">
<Binding RelativeSource="{RelativeSource FindAncestor,AncestorType=DataGridCell}" />
<Binding Path="Tag.Errors"
RelativeSource="{RelativeSource FindAncestor,AncestorType=DataGrid}" />
<Binding />
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>
<ContentPresenter />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataTemplate.Resources>
<StackPanel>
...
</StackPanel>
</DataTemplate>
</ScrollViewer.Resources>
<ContentControl Content="{Binding TableCollection}" />
</ScrollViewer>
我为Style
添加了DataGridCell
,并使用我们的额外元素定义了自定义Template
以显示!
标记
转换器类
namespace CSharpWPF
{
public class ErrorToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
DataGridColumn column = values[0] as DataGridColumn;
ObservableCollection<DataColumnChangeEventArgs> errors = values[1] as ObservableCollection<DataColumnChangeEventArgs>;
DataRowView view = values[2] as DataRowView;
DataColumnChangeEventArgs args = errors.FirstOrDefault(e => (e.Row == view.Row) && (e.Column.Ordinal == column.DisplayIndex));
return view.Row.HasErrors && args != null ? Visibility.Visible : Visibility.Collapsed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
这将检测当前单元格是受影响的单元格,如果为真,则返回Visibility.Visible
否则Visibility.Collapsed
因此隐藏或显示额外元素,具体取决于错误状态
更改CustomTable
public CustomTable()
{
...
Errors = new ObservableCollection<DataColumnChangeEventArgs>();
}
private void tableColumnChanging(object sender, DataColumnChangeEventArgs e)
{
if (!isValid(e))
{
object badValue = e.ProposedValue;
e.ProposedValue = "Bad Data";
e.Row.RowError = "The column contains an error";
e.Row.SetColumnError(e.Column, "Column cannot be " + badValue);
Errors.Add(e);
OnPropertyChanged("Errors");
}
else
{
DataColumnChangeEventArgs args = Errors.FirstOrDefault(ee => (ee.Row == e.Row) && (ee.Column == e.Column));
if (args != null)
{
Errors.Remove(args);
OnPropertyChanged("Errors");
}
//...
}
}
public ObservableCollection<DataColumnChangeEventArgs> Errors { get; set; }
结果
所以整个想法是添加一个带有通知更改功能的额外属性,并将其用作触发器和其他属性来检测相应的列,而rest是我们额外的可见性!自定义模板中的元素