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

Łuk*_*rak 20 data-binding validation wpf mvvm

当我选择(通过单击或通过键盘)我的DataGrid上的空行(当我想添加新行时),出现意外的验证错误(但没有例外) - datagrid的边框变为红色,如您所见下面的图片.当我在空行上第二次点击时,红色边框消失.其他一切工作正常,新行添加.此外,我没有任何验证规则.当我用空文本创建一行时,value是有效的.

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

在此输入图像描述

下面我附上一些源代码:

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>
Run Code Online (Sandbox Code Playgroud)

我的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);
        }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

ConfigFile类:

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

    public ConfigFile() { Name = ""; Parameters = new List<Parameter>(); }
}
Run Code Online (Sandbox Code Playgroud)

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

Łuk*_*rak 22

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

(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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 您应该将此标记为答案,因为这是一个更正确的解决方案.有关类似的解决方案,请参见http://blog.spencen.com/2009/04/30/problems-binding-to-selectedvalue-with-microsoftrsquos-wpf-datagrid.aspx. (2认同)

Jin*_*ung 9

为了解决这个问题,在Debug模式下单击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);
        }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)


Phi*_*son 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

SelectedItem="{Binding SelectedThing,Converter={conv:DataGridItemConverter}}"
Run Code Online (Sandbox Code Playgroud)