选择空行时,DataGrid上出现意外的红色边框(验证错误)

时间:2011-10-08 15:57:15

标签: wpf validation data-binding mvvm

当我选择(通过单击或通过键盘)我的DataGrid上的空白行(当我想添加新行时),出现意外的验证错误(但没有例外) - datagrid的边框变为红色,就像你一样可以在下图中看到。当我在空行上第二次点击时,红色边框消失。其他一切工作正常,新行添加。此外,我没有任何验证规则。当我用空文本创建一行时,值是有效的。

我不希望这种行为和这个红色边框,任何人都知道,为什么会发生这种情况以及如何解决这个问题?某些验证失败的原因和地点?

enter image description here

下面我附上一些源代码:

xaml中的DataGrid定义:

    <DataGrid IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name" 
 ItemsSource="{Binding Path=ConfigFiles}" SelectedItem="{Binding Path=SelectedConfigFile}" 
              Grid.Column="1" Height="87" Margin="0,26,11,32" Style="{DynamicResource DataGridStyle}">
        <DataGrid.Columns>
            <DataGridTextColumn Width="1*" Binding="{Binding Name}" />
        </DataGrid.Columns>
    </DataGrid>

我的ViewModel的部分:

public class ManageModulesVM : BaseVM  // Implements INotifyPropertyChanged
{
    // ...

    public ObservableCollection<ConfigFile> ConfigFiles
    {
        get { return selectedModule == null ? null : selectedModule.ConfigFiles; }
        set
        {
            selectedModule.ConfigFiles = value;
            OnPropertyChanged(() => ConfigFiles);
        }
    }

    public ConfigFile SelectedConfigFile
    {
        get { return selectedModule == null ? null : selectedModule.SelectedConfigFile; }
        set
        {
            if (value != null)
            {
                selectedModule.SelectedConfigFile = value;
            }
            OnPropertyChanged(() => SelectedConfigFile);
            OnPropertyChanged(() => Parameters);
        }
    }

    // ...
}

ConfigFile类:

public class ConfigFile
{
    public string Name { get; set; }
    public IList<Parameter> Parameters { get; set; }

    public ConfigFile() { Name = ""; Parameters = new List<Parameter>(); }
}

编辑: 经过进一步调查后我知道,SelectedItem绑定导致了问题(当我删除此绑定时,验证错误停止显示),但我仍然不知道为什么以及如何解决这个问题。

5 个答案:

答案 0 :(得分:21)

我找到了自己的解决方案。我写了一个值转换器并将其绑定到绑定:

(SelectedItem="{Binding Path=SelectedConfigFile,Converter={StaticResource configFileConverter}}")

转换器类:

namespace Converters
{
    public class SelectedConfigFileConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if(value is ConfigFile)
                return value;
            return null;
        }
    }
}

resources.xaml文件(或任何其他资源位置)中定义资源:

<ResourceDictionary (...) xmlns:conv="clr-namespace:Converters" >
    <conv:SelectedConfigFileConverter x:Key="configFileConverter" />
</ResourceDictionary>

此解决方案的优点是SelectedConfigFile属性的类型没有改变(对于一般的object类型),因此它仍然是强类型的。

答案 1 :(得分:8)

要了解原因,当您在调试模式下单击DataGrid的新行时,请参阅调试窗口。有第一个异常消息可以让您了解问题发生的原因。

是的,问题来自于类型转换。您需要将SelectedItem的类型修改为对象类型,如下所示。

public class ManageModulesVM : BaseVM  // Implements INotifyPropertyChanged
{
    // ...

    public object SelectedConfigFile
    {
        get { return selectedModule == null ? null : selectedModule.SelectedConfigFile; }
        set
        {
            if (value != null)
            {
                selectedModule.SelectedConfigFile = value;
            }
            OnPropertyChanged(() => SelectedConfigFile);
            OnPropertyChanged(() => Parameters);
        }
    }

    // ...
}

答案 2 :(得分:6)

这是一个通用转换器,可以用于任何DataGrid,绑定任何类型的项目:

    public class DataGridItemConverter : MarkupExtension, IValueConverter
    {
    static DataGridItemConverter converter;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
        return value;
        }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
        return (value != null && value.GetType() == targetType) ? value : null;
        }

    public override object ProvideValue(IServiceProvider serviceProvider)
        {
        if (converter == null)
            converter = new DataGridItemConverter();
        return converter;
        }
    }

由于它实现了MarkupExtension,您甚至不需要定义静态资源,您可以像这样引用它:

SelectedItem="{Binding SelectedThing,Converter={conv:DataGridItemConverter}}"

答案 3 :(得分:3)

您可以将此行添加到DataGrid:

<DataGrid  Validation.ErrorTemplate="{x:Null}" />

答案 4 :(得分:0)

您可以将此行添加到DataGrid:

<DataGrid  Validation.ErrorTemplate="{x:Null}" />

它将解决问题