【问题标题】:Automatically fix / remove invalid row from Datagrid从 Datagrid 中自动修复/删除无效行
【发布时间】:2016-08-19 08:31:36
【问题描述】:

我在 RowValidationRules 标记中有一个带有验证规则的 DataGrid。

我想要的是仅在没有验证错误的情况下更新绑定属性,否则应保留旧值。

xaml:

<DataGrid                          
Margin="10" 
CanUserAddRows="True" 
CanUserDeleteRows="True"
AutoGenerateColumns="False"
IsReadOnly="False"
ItemsSource="{Binding Source={x:Static services:SharedPropertiesProvider.Instance}, Path=Aliases, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"                        
>

<DataGrid.RowValidationRules>
    <validation:AliasValidation />
</DataGrid.RowValidationRules>
<DataGrid.Columns>
    <DataGridTextColumn Width="30*" Header="Alias" Binding="{Binding Key, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>
    <DataGridTextColumn Width="70*" Header="Path" Binding="{Binding Value, UpdateSourceTrigger=PropertyChanged}"></DataGridTextColumn>
    <DataGridTemplateColumn>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <Button Command="ApplicationCommands.Delete" Width="20" Height="20">
                    <Button.Content>
                        <Image Margin="2" Source="/WinLogInspector;component/Assets/1441392968_f-cross_256.png" />
                    </Button.Content>
                </Button>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

验证类:

class AliasValidation : ValidationRule {
public override ValidationResult Validate(object value, CultureInfo cultureInfo) {
    if (((BindingGroup)value).Items.Count > 0)
    {
        Alias item = (value as BindingGroup).Items[0] as Alias;

        if (item != null)
        {
            string aliasPattern = @"^[a-zA-Z]+[a-zA-Z0-9]*$";

            string pathPattern = @"^[a-zA-Z0-9\\/@:_\-;]+$";

            string key = item.Key ?? String.Empty;

            string path = item.Value ?? String.Empty;

            bool isValidAlias = Regex.IsMatch(key, aliasPattern);

            bool isValidPath = Regex.IsMatch(path, pathPattern);

            if (isValidAlias && isValidPath)
                return ValidationResult.ValidResult;
            else
                return new ValidationResult(false, "Invalid alias / path");
        }
    }            

    return ValidationResult.ValidResult;

} }

视图模型中的属性:

public ObservableCollection<Alias> Aliases { get; set; }

class Alias
{
    public string Key { get; set; }

    public string Value { get; set; }

}

因此,如果我尝试从视图模型执行任何命令,我可以看到 Aliases 属性具有无效行。 我该如何消毒?

【问题讨论】:

  • 我建议在 Alias ViewModel/Model 中使用 IDataErrorInfo。根据我的使用,如果验证失败,它不会更新绑定。但我很惊讶这种方法确实如此。等等,你是在对实际的 ItemsControl 执行验证吗?
  • 你是说问题是我把验证放在Datagrid而不是绑定上?
  • 我怀疑是这样,把我的想法变成一个答案。

标签: c# .net wpf xaml mvvm


【解决方案1】:

好吧,我完全错了。验证失败确实会更新绑定!目前我能想到的唯一解决方法是拥有新的显示属性,并在 setter 中进行验证......

    public string key;
    public string Key {
        get { return key; }
        set
        {
            if (key != value && this["KeyDisplay"] == string.Empty)
            {
                key = value;
                NotifyPropertyChanged("Key");
            }
        }
    }

    public string _value;
    public string Value
    {
        get { return _value; }
        set
        {
            if (_value != value && this["ValueDisplay"] == string.Empty)
            {
                _value = value;
                NotifyPropertyChanged("Value");
            }
        }
    }

    public string keyDisplay;
    public string KeyDisplay
    {
        get { return keyDisplay; }
        set
        {
            if (keyDisplay != value)
            {
                keyDisplay = value;
                Key = value;
                NotifyPropertyChanged("KeyDisplay");
            }
        }
    }

    public string valueDisplay;
    public string ValueDisplay
    {
        get { return valueDisplay; }
        set
        {
            if (valueDisplay != value)
            {
                valueDisplay = value;
                Value = value;
                NotifyPropertyChanged("ValueDisplay");
            }
        }
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == nameof(KeyDisplay) || columnName == nameof(ValueDisplay))
            {
                string aliasPattern = @"^[a-zA-Z]+[a-zA-Z0-9]*$";

                string pathPattern = @"^[a-zA-Z0-9\\/@:_\-;]+$";

                string key = KeyDisplay ?? String.Empty;

                string path = ValueDisplay ?? String.Empty;

                bool isValidAlias = Regex.IsMatch(key, aliasPattern);

                bool isValidPath = Regex.IsMatch(path, pathPattern);

                if (isValidAlias && isValidPath)
                    return string.Empty;
                else
                    return "Invalid alias / path";
            }
            return string.Empty;
        }
    }

这是原始答案,完全不正确! 验证会阻止更新与绑定关联的属性。我猜你的属性正在设置,即使它们没有通过验证是因为这些属性实际上没有被验证。您仅在 ItemsControl ItemsSource 属性上启用NotifyOnValidationError=True 验证。

对于 MVVM,我真的建议使用 IDataErrorInfo 并在 ViewModel 或 Model 中进行验证 - 验证与显示无关,在我看来也不属于视图。

class Alias : IDataErrorInfo
{
    public string Key { get; set; }

    public string Value { get; set; }

    public string this[string columnName]
    {
        get
        {
            if (columnName == nameof(Key) || columnName == nameof(Value))
            {
                string aliasPattern = @"^[a-zA-Z]+[a-zA-Z0-9]*$";

                string pathPattern = @"^[a-zA-Z0-9\\/@:_\-;]+$";

                string key = Key ?? String.Empty;

                string path = Value ?? String.Empty;

                bool isValidAlias = Regex.IsMatch(key, aliasPattern);

                bool isValidPath = Regex.IsMatch(path, pathPattern);

                if (isValidAlias && isValidPath)
                    return string.Empty;
                else
                    return "Invalid alias / path";
            }
            return string.Empty;
        }
    }

    public string Error
    {
        get
        {
            return string.Empty;
        }
    }
}

它还使您可以更灵活地检查多个属性是否有效,因为您可以访问绑定逻辑中的整个数据模型。我认为使用 ValidationRules 你可能不得不搞乱多重绑定之类的东西。

如果您在 Key 和 Value 绑定中使用了验证,则坚持使用 ValidationRules:Binding="{Binding Key, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True...}"&gt; 他们不应该在失败时更新。

【讨论】:

  • 我已经更新了代码(也有必要添加 ValidatesOnDataErrors=True),但是仍然使用了错误的数据:(
  • 刚刚测试过,你是对的。它显示在 UX 上,但仍会更新属性。多么痛苦。我一直以为它拒绝了绑定!我猜想管理它的唯一方法是拥有一个显示属性和一个数据属性 - 并且仅在有效时更新数据属性。
  • 为答案添加了解决方法。不理想(如果可能的话,我讨厌必须添加更多属性),但只要您始终记得绑定到显示属性即可。不禁想到有更好的解决方案......
  • 非常感谢您的努力 :-)
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 2015-01-21
  • 2016-08-20
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
相关资源
最近更新 更多