【问题标题】:MVVM WPF : Validating datagrid row for autogeneratedcolumnsMVVM WPF:验证自动生成列的数据网格行
【发布时间】:2014-09-04 07:44:57
【问题描述】:

我正在创建一个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 Properties -> MinLength(最小字符串长度)和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。

【问题讨论】:

  • -1 Abhishek,你现在应该知道,这不是一个你可以过来说这就是我想要的并期待的网站其他用户为你做你的工作...... 需要做的工作,只是来这里询问你是否被困在一个特定的部分。因此,我建议你去尝试满足你的要求,如果你遇到困难,那么你应该提供all relevant code来证明你的问题。
  • @Sheridan 我知道我问了很多问题。但我只是在对它进行了充分的研究后才问。我当前的 WPF 应用程序有点复杂,因此我在询问之前尝试简化问题并提供我的问题的简化示例。有些事情只是在我脑海中浮现。
  • Abhishek,这不是关于问很多问题...它是关于询问代码,而不是表明你自己已经尝试过了。由于您现在已经提供了相关代码,我现在将删除我的反对票,尽管您的代码仍然不完整并且不会重现您的问题。
  • 我们这里有一个情况。由于DataRow 没有实现INotifyPropertyChanged,所以设置RowError 或任何其他属性都不会传播到UI,因此我们不能直接执行任何触发。所以想知道DataTable 是否是必需品,或者我们也可以使用其他一些集合类?
  • @pushpraj 现在真的很难从 DataTable 移动到其他集合:(

标签: c# wpf mvvm datagrid


【解决方案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>

我为DataGridCell 添加了Style,并使用我们的额外元素定义了一个自定义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; }

结果

所以整个想法是添加一个具有通知更改功能的额外属性,并将其用作触发器和其他属性以检测适当的列,其余是我们额外的可见性!自定义模板中的元素

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-19
    • 2021-08-24
    • 2013-11-18
    • 2015-02-21
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多