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

发布于 2024-12-08 13:48:24 字数 1992 浏览 0 评论 0原文

当我选择(通过单击或通过键盘)DataGrid 上的空白行(当我想添加新行时)时,会发生意外的验证错误(但无一例外) - 数据网格的边框更改为红色,如您所见如下图。当我第二次单击空白行时,红色边框消失。其他一切工作正常,新行已添加。此外,我没有任何验证规则。当我用空文本一行时,值是有效的。

我不想要这种行为和红色边框,有人知道为什么会发生这种情况以及如何解决它?某些验证失败的原因和地点?

在此处输入图像描述

下面我附加一些源代码:

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 绑定正在导致问题(当我删除此绑定时,验证错误停止出现),但我仍然不知道为什么以及如何解决这个问题。

When I select (by clicking or by keyboard) blank row on my DataGrid (when I want to add new row), unexpected validation error occurs (but with no exception) - the border of datagrid changes to red color, as you can see on the image below. When I click second time on blank row, the red border dissapears. Everything other works fine, the new row is added. Besides, I don't have any validation rules. And when I make a row with empty text, value is valid.

I don't want this behavior and this red border, anybody knows, why this happens and how to fix it? Why and where some validation fails?

enter image description here

Below I append some source code:

DataGrid definition in xaml:

    <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>

My ViewModel's part:

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 class:

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

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

Edit:
After further investigation I know, that SelectedItem Binding is causing problems (when I remove this binding, validation error stops to appear), but I still don't know why and how to fix this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

丢了幸福的猪 2024-12-15 13:48:24

我已经找到了自己对这个问题的解决方案。我编写了一个值转换器并将其绑定到绑定:

(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 类型),因此它仍然是强类型的。

I've found my own solution to this question. I've written a value converter and tied it to the binding:

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

The converter class:

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;
        }
    }
}

Define resource in resources.xaml file (or in any other resources place):

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

The advantage of this solution is that the SelectedConfigFile property's type did't changed (to the general object type) so it is still strongly typed.

三生殊途 2024-12-15 13:48:24

要了解原因,当您在调试模式下单击 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);
        }
    }

    // ...
}

To get the reason, when you click the new row of DataGrid in Debug mode, please see the debug window. There are first exception messages which will give you the idea why your problem is occurred.

Yes, the problem is from type casting. You need to modify the type of SelectedItem to object type as below.

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

    // ...
}
风为裳 2024-12-15 13:48:24

这是一个通用转换器,您可以用于任何 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}}"

Here's a general-purpose converter you can use for any DataGrid, binding any kind of item:

    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;
        }
    }

Since it implements MarkupExtension you don't even need to define a static resource, you can just reference it like this:

SelectedItem="{Binding SelectedThing,Converter={conv:DataGridItemConverter}}"
享受孤独 2024-12-15 13:48:24

您只需将此行添加到 DataGrid 即可:

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

You can just add this line to your DataGrid:

<DataGrid  Validation.ErrorTemplate="{x:Null}" />
鹊巢 2024-12-15 13:48:24

您只需将此行添加到您的 DataGrid:

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

它将解决问题

You can just add this line to your DataGrid:

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

It will solve the problem

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文