自动修复/删除Datagrid中的无效行

时间:2016-08-19 08:31:36

标签: c# .net wpf xaml mvvm

我在 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;

} }

viewmodel中的属性:

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

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

    public string Value { get; set; }

}

因此,如果我尝试从viewmodel执行任何命令,我可以看到 Aliases 属性具有无效行。 我怎样才能消毒呢?

1 个答案:

答案 0 :(得分: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...}">他们不应该在失败时更新。