WPF DataGrid 绑定验证和转换问题

发布于 2024-11-17 03:10:31 字数 3038 浏览 9 评论 0原文

我想知道 DataGrid 绑定对于不同类型的错误有何不同的行为。 我已经设置了一个示例项目:

数据类:

public class MajorEvent : INotifyPropertyChanged, IDataErrorInfo
{
    private DateTime when;
    public DateTime When
    {
        get { return when; }
        set
        {
            if (value > DateTime.Now)
            {
                throw new ArgumentOutOfRangeException("value", "A Major event can't happen in the future!");
            }
            when = value;
        }
    }

    public string What { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName.Equals("What"))
            {
                if (string.IsNullOrEmpty(What))
                {
                    return "An event needs an agenda!";
                }
            }
            return string.Empty;
        }
    }

    public string Error
    {
        get { return null; }
    }
}

主窗口代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        dg.ItemsSource = new ObservableCollection<MajorEvent>
                             {
                                 new MajorEvent {What = "Millenium celebrations", When = new DateTime(1999, 12, 31)},
                                 new MajorEvent {What = "I Have A Dream Speach", When = new DateTime(1963, 8, 28)},
                                 new MajorEvent {What = "First iPhone Release", When = new DateTime(2007, 6, 29)},
                                 new MajorEvent {What = "My Birthday", When = new DateTime(1983, 5, 13)},
                                 new MajorEvent {What = "Friends Backstabbing Day", When = new DateTime(2009, 6, 8)},
                             };
    }


}

和 MainWindow Xaml:

<Window x:Class="DataGridValidationIssue.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="dg" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="What" Binding="{Binding What, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="*"/>
                <DataGridTextColumn Header="When" Binding="{Binding When, StringFormat='d', ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="Auto"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

现在,关于日期列 - 当我输入未来日期(从而导致 ArgumentOutOfRangeException)时,文本列仍然可以编辑。当我提供无效日期(例如 5 月 35 日)时,则无法编辑文本列。

为什么 WPF 会有这样的行为?

I was wondering how does the DataGrid Binding behaves differently for different kind of errors.
I've set up a sample project:

The Data Class:

public class MajorEvent : INotifyPropertyChanged, IDataErrorInfo
{
    private DateTime when;
    public DateTime When
    {
        get { return when; }
        set
        {
            if (value > DateTime.Now)
            {
                throw new ArgumentOutOfRangeException("value", "A Major event can't happen in the future!");
            }
            when = value;
        }
    }

    public string What { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName.Equals("What"))
            {
                if (string.IsNullOrEmpty(What))
                {
                    return "An event needs an agenda!";
                }
            }
            return string.Empty;
        }
    }

    public string Error
    {
        get { return null; }
    }
}

Main Window Code Behind :

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        dg.ItemsSource = new ObservableCollection<MajorEvent>
                             {
                                 new MajorEvent {What = "Millenium celebrations", When = new DateTime(1999, 12, 31)},
                                 new MajorEvent {What = "I Have A Dream Speach", When = new DateTime(1963, 8, 28)},
                                 new MajorEvent {What = "First iPhone Release", When = new DateTime(2007, 6, 29)},
                                 new MajorEvent {What = "My Birthday", When = new DateTime(1983, 5, 13)},
                                 new MajorEvent {What = "Friends Backstabbing Day", When = new DateTime(2009, 6, 8)},
                             };
    }


}

and MainWindow Xaml:

<Window x:Class="DataGridValidationIssue.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="dg" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="What" Binding="{Binding What, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="*"/>
                <DataGridTextColumn Header="When" Binding="{Binding When, StringFormat='d', ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Width="Auto"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Now, regarding the date column - when I enter a future date (thus causing an ArgumentOutOfRangeException) the text column can still be edited. When I'm providing an invalid date (for example, May 35'th), then the text column can not be edited.

Why does WPF behave like this?

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

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

发布评论

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

评论(1

我也只是我 2024-11-24 03:10:31

DateTime 范围内的默认验证行为是,当您输入无法转换为 DateTime 的字符串时(即 5 月 35 日或其他奇特的事情),抛出异常。一旦抛出异常,TextBox 就会被阻止

。在您的情况下,您没有检查 IDataErrorInfo 实现中的日期值! (如果需要,请在此处了解有关 IDataErrorInfo 的更多信息

抛出异常似乎是合乎逻辑的遵循默认的 DateTime 验证过程,因为您正在验证异常。您应该在 this[string propertyName] 处理日期范围中添加一个案例(我认为您必须在此处为“When”属性添加一个案例,测试日期范围)

Default validation behavior in a DateTime scope is to throw an Exception when you enter a String that cannot be converted into a DateTime (ie May 35th or another fancy thing). Once the exception thrown, the TextBox is blocked

In your case, you are not checking the Date value in your IDataErrorInfo implementation! ( more information about IDataErrorInfo here if needed )

It seems logical that an exception is thrown following the default DateTime validation process, since you are validating on exceptions. You should add a case in your this[string propertName] handling Date range (I think you have to add a case for the "When" property here, testing the date range)

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